以AppCrawler的配置文件完成定制化的自动遍历测试(基础)-01

1,353 阅读3分钟

1、前情回顾

在上一篇中已经初步的认识了自动遍历测试技术以及工具的选择和快如入门,对过对比和需求,最终选择以testerhome社区联合创始人,前阿里、百度和雪球的测试架构师思寒大佬的AppCrawler作为自动遍历测试的工具,详细回顾可参考博客: 初探自动遍历测试工具-AppCrawler

2、定制化配置

2.1模板文件生成

  • 运行命令java -jar appcrawler-2.4.0-jar-with-dependencies.jar --demo,会在当前目录下生成一个demo.yml文件,这个文件就是我们进行定制化的配置文件模板:
    #执行命令生成demo.yaml模板配置文件
    $ java -jar appcrawler-2.4.0-jar-with-dependencies.jar --demo
    2019-12-01 21:33:35 INFO [AppCrawler$.86.main]
    ----------------
    AppCrawler 2.4.0 [霍格沃兹测试学院特别纪念版]
    Appium 1.8.1 Java8 tested
    app爬虫, 用于自动遍历测试. 支持Android和iOS, 支持真机和模拟器
    项目地址: https://github.com/seveniruby/AppCrawler
    移动测试技术交流: https://testerhome.com
    联络作者: seveniruby@testerhome.com (思寒)
    致谢: 晓光 泉龙 杨榕 恒温 mikezhou yaming116 沐木
    
    --------------------------------
    
    2019-12-01 21:33:35 INFO [AppCrawler$.223.parseParams] use default appium address 4723
    2019-12-01 21:33:35 INFO [AppCrawler$.230.parseParams] appium address = Some(http://127.0.0.1:4723/wd/hub)
    2019-12-01 21:33:35 INFO [AppCrawler$.242.parseParams] result directory = 20191201213335
    2019-12-01 21:33:36 INFO [AppCrawler$.286.parseParams] you can read /Users/qinzhen/Documents/TestDev/AppCrawler/demo.yml for demo
    
    #查看配置文件已生成
    $ ls
    appcrawler-2.4.0-jar-with-dependencies.jar
    demo.yml
    
  • 打开配置文件demo.yaml如下:
    ---
    pluginList: []
    saveScreen: true
    reportTitle: ""
    resultDir: "20191201213335"
    waitLoading: 500
    waitLaunch: 6000
    showCancel: true
    maxTime: 10800
    maxDepth: 10
    capability:
      noReset: "true"
      fullReset: "false"
      appium: "http://127.0.0.1:4723/wd/hub"
    testcase:
      name: "TesterHome AppCrawler"
      steps:
      - given: []
        when: null
        then: []
        xpath: "/*"
        action: "Thread.sleep(5000)"
        actions: []
        times: 0
    selectedList:
    - given: []
      when: null
      then: []
      xpath: "//*[contains(name(), 'Button')]"
      action: null
      actions: []
      times: 0
    - given: []
      when: null
      then: []
      xpath: "//*[contains(name(), 'Text') and @clickable='true' and string-length(@text)<10]"
      action: null
      actions: []
      times: 0
    - given: []
      when: null
      then: []
      xpath: "//*[@clickable='true']/*[contains(name(), 'Text') and string-length(@text)<10]"
      action: null
      actions: []
      times: 0
    - given: []
      when: null
      then: []
      xpath: "//*[contains(name(), 'Image') and @clickable='true']"
      action: null
      actions: []
      times: 0
    - given: []
      when: null
      then: []
      xpath: "//*[@clickable='true']/*[contains(name(), 'Image')]"
      action: null
      actions: []
      times: 0
    - given: []
      when: null
      then: []
      xpath: "//*[contains(name(), 'Image') and @name!='']"
      action: null
      actions: []
      times: 0
    - given: []
      when: null
      then: []
      xpath: "//*[contains(name(), 'Text') and @name!='' and string-length(@label)<10]"
      action: null
      actions: []
      times: 0
    firstList: []
    lastList:
    - given: []
      when: null
      then: []
      xpath: "//*[@selected='true']/..//*"
      action: null
      actions: []
      times: 0
    - given: []
      when: null
      then: []
      xpath: "//*[@selected='true']/../..//*"
      action: null
      actions: []
      times: 0
    backButton:
    - given: []
      when: null
      then: []
      xpath: "Navigate up"
      action: null
      actions: []
      times: 0
    triggerActions:
    - given: []
      when: null
      then: []
      xpath: "share_comment_guide_btn"
      action: null
      actions: []
      times: 0
    xpathAttributes:
    - "name"
    - "label"
    - "value"
    - "resource-id"
    - "content-desc"
    - "instance"
    - "text"
    sortByAttribute:
    - "depth"
    - "list"
    - "selected"
    findBy: "default"
    defineUrl: []
    baseUrl: []
    appWhiteList: []
    urlBlackList: []
    urlWhiteList: []
    blackList:
    - given: []
      when: null
      then: []
      xpath: ".*[0-9]{2}.*"
      action: null
      actions: []
      times: 0
    beforeRestart: []
    beforeElement:
    - given: []
      when: null
      then: []
      xpath: "/*"
      action: "Thread.sleep(500)"
      actions: []
      times: 0
    afterElement: []
    afterPage: []
    afterPageMax: 2
    tagLimitMax: 2
    tagLimit:
    - given: []
      when: null
      then: []
      xpath: "确定"
      action: null
      actions: []
      times: 1000
    - given: []
      when: null
      then: []
      xpath: "取消"
      action: null
      actions: []
      times: 1000
    - given: []
      when: null
      then: []
      xpath: "share_comment_guide_btn_name"
      action: null
      actions: []
      times: 1000
    assertGlobal: []
    

2.2 执行参数

同样,还是以雪球App为例,以实际操作运行来解释配置文件中各个参数的含义和用法

  • capability设置: 与appium完全一致,但要注意这里默认有noReset: "true"appium: "http://127.0.0.1:4723/wd/hub" 属性,配置完成如下

    capability:
      noReset: "false"
      fullReset: "false"
      appium: "http://127.0.0.1:4723/wd/hub"
      appPackage: com.xueqiu.androi
      appActivity: .view.WelcomeActivityAlias
      automationName: uiautomator2
      autoGrantPermissions: true
    

    这里再介绍两个很有趣也很有用的参数:
    dontStopAppOnReset: true ;这个参数允许我们在某个页面继续执行遍历,比如我们希望App先进入到某个页面后再进行遍历,或者当一个session结束后继续下一个session的时候我们希望不要杀死App重新执行,而是继续上一次结束的页面开始执行
    ignoreUnimportantViews: 这个参数设置为true的时候可以忽略不重要的view,加速pageSource的加载,加快测试速度

  • testcase: 用于启动APP后的基础测试用例 完整形态: 允许我们以givenwhenthen的形式指定操作,如果学习过Java的接口自动化框架rest-assured话可以很容易理解这三个参数表达的含义:

    • given: 所有的先决条件,给定一个条件,只有条件成立的时候才完成后面的操作(实际用的较少)
    • when: 先决条件成立后的行为,对什么事件做什么事情
    • then: 断言集合,事件结束后对结果断言 具体写法如下:
    testcase:
      name: "TesterHome AppCrawler"
      steps:
       - when: 
    		xpath: //*
    		action: driver.swipe(0.5, 0.8, 0.5, 0.2)
       - when: 
    		xpath: //*
    		action: driver.swipe(0.5, 0.2, 0.5, 0.8)
         then: 
         - //*[contains(@text, '美股')]	
    

    简写形态: 另外实际使用中我们会经常使用简写形态

    • 直接使用xpath对应when里面的xpath
    • 直接使用action对应when里面的action 具体写法如下:
    - xpath: 自选
      action: click
      then:
      - //*[contains(@text, '美股')]	
    
    • action的动作支持
      • "" :只是截图记录
      • back:后退
      • backApp:回退到当前的App,默认等价于back行为 可定制
      • monkey:随机事件
      • xxx()执行代码:
        • Thread.sleep(1000)
        • driver.swipe(0.9,0.8,0.9,0.5)
      • click:点击事件
      • longTap:长按
      • 除以上所有行为外均视为输入行为

    注:定位模式除了可以使用xpath之外还可以使用正则和包含关系,只不过经常使用的是xpath,也更为严谨;

    • 正则:使用^开头的就认定为正则,^确定$^.*输入密码
    • 包含:可以使用元素其中包含的内容进行定位; 密码输入 这里以雪球首页搜索框输入alibaba的简单场景举例,在搜索前还需要处理掉升级弹框,修改完成如下:
    testcase:
      name: "XueQiuTestDemo AppCrawler"
      steps:
      - { xpath: "//*[contains(@resource-id,'image_cancel')]", action: click }
      - xpath: home_search
        action: click
      - xpath: search_input_text
        action: alibaba
    

    如上的testcase写法还要多说几句:

    • 也可以使用{}将需要执行的事件包裹起来,元素定位符和操作action时间用逗号隔开
    • {}内若使用xpath表达式的话需要加双引号
    • xpath中直接写idtext文本信息,就会默认使用包含去查找
    • 需要点击的事件要明确指明click,某则会报错;虽然思寒说过默认的action就是click,但是经过实测发现在2.4.0版本上必须指明action:click;很可能是思寒本地使用的内部版本经过了优化更新还未来得及开源到GitHub上

    运行效果

    在这里插入图片描述

  • selectedList: 遍历范围设定 这里如果想设置让其点击所有可点击的TextViewImageView控件,修改完成如下:

    selectedList:
    - xpath: //android.widget.ImageView[@clickable='true']
    - xpath: //*[@clickable='true' and contains(@class,"Text")]
    
  • firstList: 优先被点击

  • lastList:最后执行 设置其最后才执行"确定"按钮,修改完成如下:

    lastList:
    - { xpath: text_yes, action: click }
    
  • backButton: 当所有元素都被点击后默认后退控件定位

  • blackList:黑名单

  • triggerAction: 特定条件出发执行动作的设置;设置遇到重置密码输入框时输入123456abc两次,修改完成如下:

    triggerActions:
    - { xpath: android.widget.EditText, action: 123456abc, times: 2 }
    
  • tagLimitMax: 全局设置,同类型的最多点击的次数;这里设置为2次

    tagLimitMax: 2
    
  • tagLimit: 自定义控件类型的点击次数,这里设置对于ListView类型的只点击一次; 修改完成如下

    - { xpath: "//*[contains(@class, 'List')]//*", times: 1 }
    
  • maxDepth: 遍历的最大深度

  • assertGlobal:设置一个全局断言,例如可设置断言在当前App,如果包名不符合,就可能发生了崩溃,便会报错

注:执行参数比配置文件优先级高

3、写在最后

到这里,appcrawler的基本语法和参数含义大致介绍了一遍,后面就是如何结合实际进行使用了,具体可参考另一篇: 以AppCrawler的配置文件完成定制化的自动遍历测试(实操)-02