TA的每日心情 | 无聊 昨天 09:34 |
---|
签到天数: 1052 天 连续签到: 2 天 [LV.10]测试总司令
|
1测试积点
总结来说就是用一种自动化回归脚本的方式,可以重复性的回归现有功能,并给出回归测试报告。
基于这个想法,我开发了这个脚本,定义了一套开发模式,基于这个模式,只要针对每个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()
复制代码
|
|