基于Splinter的自动化回归/测试脚本

发表于:2020-12-31 10:35

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:苍术厚朴    来源:博客园

  总结来说就是用一种自动化回归脚本的方式,可以重复性的回归现有功能,并给出回归测试报告。
  基于这个想法,我开发了这个脚本,定义了一套开发模式,基于这个模式,只要针对每个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()  

      本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号