AppCrawer使用(2)
1、查看帮助文档
java -jar appcrawler-2.4.0-jar-with-dependencies.jar ---------------- 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 沐木 -------------------------------- Usage: appcrawler [options] -a, --app <value> Android或者iOS的文件地址, 可以是网络地址, 赋值给appium的app选项 #安装App,实际中使用较少 -e, --encoding <value> set encoding, such as UTF-8 GBK #在Windows下可能会产生乱码,对其编码格式进行设置 -c, --conf <value> 配置文件地址 #复杂且重要,是AppCrawler定制的核心 -p, --platform <value> 平台类型android或者ios, 默认会根据app后缀名自动判断 -t, --maxTime <value> 最大运行时间. 单位为秒. 超过此值会退出. 默认最长运行3个小时 -u, --appium <value> appium的url地址 #运行依赖于appium,不加此参数就使用默认的appium地址端口 -o, --output <value> 遍历结果的保存目录. 里面会存放遍历生成的截图, 思维导图和日志 --capability k1=v1,k2=v2... # 和appium的capability设置一致 appium capability选项, 这个参数会覆盖-c指定的配置模板参数, 用于在模板配置之上的参数微调 -r, --report <value> 输出html和xml报告 --template <value> 输出代码模板 --master <value> master的diff.yml文件地址 --candidate <value> candidate环境的diff.yml文件 --diff 执行diff对比 -vv, --verbose 是否展示更多debug信息 --demo 生成demo配置文件学习使用方法 --help 示例 appcrawler -a xueqiu.apk appcrawler -a xueqiu.apk --capability noReset=true appcrawler -c conf/xueqiu.json -p android -o result/ appcrawler -c xueqiu.json --capability udid=[你的udid] -a Snowball.app appcrawler -c xueqiu.json -a Snowball.app -u 4730 appcrawler -c xueqiu.json -a Snowball.app -u http://127.0.0.1:4730/wd/hub #生成demo例子 appcrawler --demo #启动已经安装过的app appcrawler --capability "appPackage=com.xueqiu.android,appActivity=.view.WelcomeActivityAlias" #从已经结束的结果中重新生成报告 appcrawler --report result/ #新老版本对比 appcrawler --candidate result/ --master pre/ --report ./
启动步骤:
1、appium启动
2、adb 连接 adb connect 127.0.0.1:21503 【逍遥模拟器,夜神是62001】
3、demo.yml生成【生成的yml不能直接作为参数运行,需要编辑后保存为yaml文件方可】
ps:曾经遇到的坑 报空指针异常,原来是配置文件中配置项若无数据,那么列表符号一定要
4、参数运行 D:\appcrawler>java -jar appcrawler-2.4.0-jar-with-dependencies.jar --capability "appPackage=com.mmkt.online.edu,appActivity=.view.activity.SplashActivity" -c demo.yaml
5、参数文件【以自己公司项目为例】
配置文件的说明可参考:https://github.com/seveniruby/AppCrawler/blob/2.3.1/src/main/scala/com/testerhome/appcrawler/CrawlerConf.scala
--- pluginList: [] saveScreen: true reportTitle: "第一次" resultDir: "20200525164007" waitLoading: 500 waitLaunch: 6000 showCancel: true maxTime: 10800 maxDepth: 10 capability: noReset: "false" fullReset: "false" appium: "http://127.0.0.1:4723/wd/hub" appPackage: com.mmkt.online.edu appActivity: .view.activity.SplashActivity automationName: uiautomator2 autoGrantPermissions: true testcase: name: "TesterHome AppCrawler" steps: [] # - {xpath: 请输入手机号, # action: 18380472869, # times: 1} # - {xpath: 请输入密码, # action: 12345678mmkt, # times: 1} # - {xpath: 登录, # action: click, # times: 1} 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: [] # - { # action: 18380472869, # xpath: "//*[@resource-id='com.mmkt.online.edu:id/edt_phone']", # times: 1} # - { # action: 12345678mmkt, # xpath: "//*[@resource-id='com.mmkt.online.edu:id/edt_password']", # times: 1} # - { # action: click, # xpath: "//*[@resource-id='com.mmkt.online.edu:id/btn_login']", # times: 1} lastList: - {xpath: "//*[@resource-id='btnExit']", action: click, times: 1} # - 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: - { action: 18380472869, xpath: "//*[@resource-id='com.mmkt.online.edu:id/edt_phone']", times: 1} - { action: 12345678mmkt, xpath: "//*[@resource-id='com.mmkt.online.edu:id/edt_password']", times: 1} - { action: click, xpath: "//*[@resource-id='com.mmkt.online.edu:id/btn_login']", times: 1} xpathAttributes: - "name" - "label" - "value" - "resource-id" - "content-desc" - "instance" - "text" sortByAttribute: - "depth" - "list" - "selected" findBy: "default" defineUrl: [] baseUrl: [] appWhiteList: [] urlBlackList: - //*[contains(@resource-id, "com.mmkt.online.edu:id/btnCancel") and @clickable='true'] urlWhiteList: - //*[contains(@resource-id, "com.mmkt.online.edu:id/main_rd_5") and @clickable='true'] blackList: - xpath: ".*[0-9]{2}.*" - xpath: //*[@resource-id='com.mmkt.online.edu:id/btnCancel'] - xpath: //*[@resource-id="com.mmkt.online.edu:id/action_bar_root"] - xpath: //*[@resource-id="android:id/content"] - xpath: //*[@resource-id="com.vphone.launcher:id/launcher"] - xpath: //*[@resource-id="com.vphone.launcher:id/drag_layer"] - xpath: //*[@resource-id="com.vphone.launcher:id/workspace"] - xpath: //*[@content-desc="Google Search"] - xpath: //*[@resource-id="com.vphone.launcher:id/qsb_ll"] - xpath: //*[@resource-id="com.vphone.launcher:id/btn_icon"] - xpath: //*[@resource-id="com.vphone.launcher:id/ll_main"] - xpath: //*[@resource-id="com.vphone.launcher:id/search_content"] - xpath: //*[@resource-id="com.vphone.launcher:id/llayout_normal"] - xpath: //*[@resource-id="com.vphone.launcher:id/recyclerview_search_ranking"] - xpath: //*[@resource-id="com.vphone.launcher:id/ll_item"] - xpath: //*[@resource-id="com.vphone.launcher:id/dpb_download"] - xpath: //*[@text="打开" and @resource-id="com.vphone.launcher:id/tv_download"] 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: []
参数使用说明:
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.mmkt.online.edu appActivity: .view.activity.SplashActivity automationName: uiautomator2 autoGrantPermissions: true
这里再介绍两个有用的参数:
dontStopAppOnReset: true ;这个参数允许我们在某个页面继续执行遍历,比如我们希望App先进入到某个页面后再进行遍历,或者当一个session结束后继续下一个session的时候我们希望不要杀死App重新执行,而是继续上一次结束的页面开始执行
ignoreUnimportantViews: 这个参数设置为true的时候可以忽略不重要的view,加速pageSource的加载,加快测试速度
testcase: 用于启动APP后的基础测试用例:
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:长按
除以上所有行为外均视为输入行为
正则:使用^开头的就认定为正则,^确定$,^.*输入密码
包含:可以使用元素其中包含的内容进行定位; 密码,输入,请
这里以雪球首页搜索框输入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
注意:
也可以使用{}将需要执行的事件包裹起来,元素定位符和操作action时间用逗号隔开
{}内若使用xpath表达式的话需要加双引号
xpath中直接写id或text文本信息,就会默认使用包含去查找
需要点击的事件要明确指明click,某则会报错;虽然思寒说过默认的action就是click,但是经过实测发现在2.4.0版本上必须指明action:click;
selectedList: 遍历范围设定
这里如果想设置让其点击所有可点击的TextView
和ImageView
控件,修改完成如下:
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,如果包名不符合,就可能发生了崩溃,便会报错