總結來說就是用一種自動化回歸腳本的方式,可以重復性的回歸現有功能,並給出回歸測試報告
基於這個想法,我開發了這個腳本,定義了一套開發模式,基於這個模式,只要針對每個case添加如下的腳本代碼:
caseBegin('輸入關鍵字執行搜索') ——>測試開始,其實就是打印一個日志 reset(__url) ——>重置訪問指定URL,如s.etao.com addQ('nokia') ——>添加Q參數,搜索框只有一個固定的q參數可以輸入 submit() ——>提交搜索表單 jumpUrl('auctions.htm') ——>我們期望結果會跳轉到auctions.htm,也可以指定在頁面什么區域顯示什么內容, 目前支持三種: 1、結果外跳到某個頁面,這個內部會根據指定的頁面名稱生成一個匹配正則; 2、本頁面提示某個信息; 3、跳轉到外部某個頁面提示某個信息; caseEnd() ——>測試結束,其實沒有做什么,只是打了日志保存結果,可以擴展成郵件發送之類
通過現在的自動腳本跑出來的結果:
檢查[http://m.etao.com能否正常訪問]:
pass.
-------------------[End]-----------------------
檢查[未輸入關鍵字執行搜索]:
期望結果:在本頁面中提示信息請輸入品牌或型號進行比價
pass.
-------------------[End]-----------------------
檢查[輸入關鍵字執行搜索]:
期望結果:頁面跳轉到auctions.htm
pass.
-------------------[End]-----------------------
檢查[搜索列表頁輸入空關鍵字搜索]:
期望結果:跳轉到頁面:index.htm,提示信息:請輸入品牌或型號進行比價
期望結果:頁面跳轉到index.htm
pass.
期望結果:在本頁面中提示信息請輸入品牌或型號進行比價
pass.
-------------------[End]-----------------------
檢查[輸入關鍵字搜索]:
期望結果:頁面跳轉到auctions.htm
pass.
-------------------[End]-----------------------
可以較為清晰的看到回歸了哪些功能,結果是怎樣的。將人肉從重復性的工作中解放出來。例子是在一淘項目中使用的代碼,但是具體的步驟庫是通用的。
現在腳本的開發上可能比較復雜,需要涉及python,splinter,正則甚至是jquery的部分語法,后續打算采用自動生成的方式來做。
如果大家有其他好的想法,非常歡迎一起交流碰撞
#!/user/bin/python # -*- coding: utf8 -*- import sys import re from splinter.browser import Browser ##################################################### # global instance CLOASE_AFTER_TEST = True # 測試完畢是否自動關閉瀏覽器 GBK = "gbk" UTF8 = "utf8" ##################################################### # encoding for console reload(sys) sys.setdefaultencoding(UTF8) ##################################################### # small method encoding = lambda x:x.encode(GBK) ##################################################### # Method output def output(x): """ encode and print """ print encoding(x) # Method resultMsg def resultMsg(x, msg=''): """ judge result and print, x : True or False """ if x == True: output('pass.') else: output('[X]not pass.'+msg) # Method infoMsgThisPage def infoMsgThisPage(espectMsg, positionPattern, getPositionMethodName): """ 在本頁面提示信息 espectMsg:期望提示的信息 positionPattern:位置匹配串,根據getPositionMethodName參數的不同而不同類型 getPositionMethodName:獲取位置的方法,有Splinter提供,可選擇列表 使用CSS方式查找: find_by_css 使用Xpath查詢語言: find_by_xpath 使用Tag查找:find_by_tag 使用name查找:find_by_name 使用id查找:find_by_id 使用value查找:find_by_value """ output('期望結果:在本頁面中提示信息'+espectMsg) function = getattr(browser, getPositionMethodName) if callable(function): errorbox = function(positionPattern) if errorbox is not None and len(errorbox) == 1: resultMsg(espectMsg == errorbox[0].value) elif len(errorbox) > 1: resultMsg(False, '根據您指定的錯誤信息位置匹配串,頁面含有一個以上的錯誤顯示區域,請檢查頁面') else: resultMsg(False, '根據您指定的錯誤信息位置匹配串,頁面沒有找到錯誤顯示區域,請檢查頁面') else: resultMsg(False, 'ERROR:method'+function+'is not callable.') # Method jumpUrl def jumpUrl(urlPattern): """ 頁面跳轉出去到新的頁面提示信息,使用本方法不關注頁面提示內容,僅僅關注跳轉頁面是否正常 urlPattern:期望跳轉到的頁面的匹配串,可以是普通頁面名稱 """ output('期望結果:頁面跳轉到'+urlPattern) if urlPattern[-1] != '/': pattern = "^("+urlPattern+"\?).*" urlPattern = urlPattern + "?" # 截取出來的會帶有一個?,所以這里也要加一個,否則無法相等 else: pattern = "^("+urlPattern+").*" r = re.search(re.compile(pattern, re.IGNORECASE), browser.url) if r is not None and len(r.groups()) == 1: resultMsg(urlPattern == "".join(["%s" % s for s in r.groups()]), '未跳轉到指定結果頁面') elif r is not None and len(r.groups()) > 1: resultMsg(False, '在跳轉結果URL中找到了兩個'+urlPattern+'相關的串,請檢查是否有問題') else: resultMsg(False, '跳轉結果URL中沒有找到'+urlPattern) # Method : jumpUrlAndInfoMsg def jumpUrlAndInfoMsg(urlPattern, espectMsg, positionPattern, getPositionMethodName): """ 頁面跳轉到指定頁面,提示指定信息 具體參數請參見 jumpUrl 方法和 infoMsgThisPage 方法 """ output('期望結果:跳轉到頁面:'+urlPattern+',提示信息:'+espectMsg) jumpUrl(urlPattern) infoMsgThisPage(espectMsg, positionPattern, getPositionMethodName) ##################################################### # 頁面錯誤提示文案 ERROR_WITHOUT_Q = "請輸入品牌或型號進行比價" ##################################################### # 開始執行測試邏輯部分 browser = Browser() __url = 'http://m.etao.com' reset = lambda x:browser.visit(x) submit = lambda:browser.find_by_value('比價').first.click() addQ = lambda q:browser.fill('q', q.decode(UTF8)) caseEnd = lambda:output('-------------------[End]-----------------------') caseBegin = lambda m:output('檢查['+m+']:') try: # check service is ok or not caseBegin(__url+"能否正常訪問") reset(__url) resultMsg(browser.status_code.is_success()) caseEnd() # without q caseBegin('未輸入關鍵字執行搜索') addQ(' ') submit() infoMsgThisPage(ERROR_WITHOUT_Q, "div[class='detail blue-box Amazing']", 'find_by_css') caseEnd() # with q caseBegin('輸入關鍵字執行搜索') reset(__url) addQ('nokia') submit() jumpUrl('http://s.m.etao.com/auctions.htm') caseEnd() caseBegin('搜索列表頁輸入空關鍵字搜索') reset('http://s.m.etao.com/auctions.htm?q=nokia') addQ(' ') submit() jumpUrlAndInfoMsg('http://s.m.etao.com/index.htm', ERROR_WITHOUT_Q, "div[class='detail blue-box Amazing']", 'find_by_css') caseEnd() caseBegin('輸入關鍵字搜索') reset('http://s.m.etao.com/auctions.htm?q=nokia') addQ('手機') submit() jumpUrl('http://s.m.etao.com/auctions.htm') caseEnd() except Exception, e: print e if CLOASE_AFTER_TEST: browser.quit()