51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 3873|回复: 7
打印 上一主题 下一主题

[转贴] AppCrawler 自动遍历工具 2.0 版本发布

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2017-6-26 10:39:47 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
自动遍历的价值

自动化探索测试, 遍历基本的界面, 了解主要界面的可用性. 比如兼容性, 基本功能
利用遍历获取app的加载时间和性能数据, 需要借助其他的性能数据抓取工具,比如OneApm, NewRelic
利用遍历验证app的内存泄漏以及稳定性等功能, 需要借助LeakCanary和MLeaksFinder
自动化回归测试. UI diff 验证新老版本的功能差异. 并识别细节的问题
抓取接口请求 辅助验证一些模块基本接口, 并辅助分析接口调用流程. 为接口测试做准备
截图

使用介绍
  1. ----------------
  2. AppCrawler 2.0.0
  3. app爬虫, 用于自动遍历测试. 支持Android和iOS, 支持真机和模拟器
  4. 帮助文档: http://seveniruby.gitbooks.io/appcrawler
  5. 移动测试技术交流: https://testerhome.com
  6. 感谢: 晓光 泉龙 杨榕 恒温 mikezhou yaming116
  7. 感谢提供商业支持的优秀公司: Keep
  8. --------------------------------


  9. Usage: appcrawler [options]

  10.   -a, --app <value>        Android或者iOS的文件地址, 可以是网络地址, 赋值给appium的app选项
  11.   -c, --conf <value>       配置文件地址
  12.   -p, --platform <value>   平台类型android或者ios, 默认会根据app后缀名自动判断
  13.   -t, --maxTime <value>    最大运行时间. 单位为秒. 超过此值会退出. 默认最长运行3个小时
  14.   -u, --appium <value>     appium的url地址
  15.   -o, --output <value>     遍历结果的保存目录. 里面会存放遍历生成的截图, 思维导图和日志
  16.   --capability k1=v1,k2=v2...
  17.                            appium capability选项, 这个参数会覆盖-c指定的配置模板参数, 用于在模板配置之上的参数微调
  18.   -r, --report <value>     输出html和xml报告
  19.   --template <value>       输出代码模板
  20.   --master <value>         master的diff.yml文件地址
  21.   --candidate <value>      candidate环境的diff.yml文件
  22.   --diff                   执行diff对比
  23.   -vv, --verbose           是否展示更多debug信息
  24.   --help
  25. 示例
  26. appcrawler -a xueqiu.apk
  27. appcrawler -a xueqiu.apk --capability noReset=true
  28. appcrawler -c conf/xueqiu.json -p android -o result/
  29. appcrawler -c xueqiu.json --capability udid=[你的udid] -a Snowball.app
  30. appcrawler -c xueqiu.json -a Snowball.app -u 4730
  31. appcrawler -c xueqiu.json -a Snowball.app -u http://127.0.0.1:4730/wd/hub

  32. #启动已经安装过的app
  33. appcrawler --capability appPackage=com.xueqiu.android,appActivity=.welcomeActivity

  34. #从已经结束的结果中重新生成报告
  35. appcrawler --report result/

  36. #新老版本对比
  37. appcrawler --candidate result/ --master pre/ --report ./

  38. #自动生成Page Object代码模板文件
  39. appcrawler --template PageObjectDemo.ssp --output result/

  40. #根据wda的inspector生成测试用例代码
  41. appcrawler --template PageObjectDemo.ssp -u http://localhost:8100
复制代码
重构和不兼容改动
重构了一半多的代码. 提升了性能, 改进测试用例生成的方式. 更快更稳定.
所有的action字段都支持简单的动作和完整的scala编程语句, 样例如下

click 点击
tap 长按
driver.swipe(0.8, 0.8, 0.2, 0.2) 滑动
back 后退
backApp 从其他的app回退到当前app
非以上内容都认为是输入文本
以前的是MiniAppium.xxx, 新版本修改为driver.xxx, 这个driver就是selenium的driver

Appium失败重试

如果appium崩溃了(主要是uiautomator的崩溃), appcrawler会自动重启appium继续测试.
这样需要修改你的遍历配置, 设置为 dontStopAppOnReset: true
  1. androidCapability:
  2.   deviceName: "192.168.0.102:5555"
  3.   appPackage: "com.gotokeep.keep"
  4.   appActivity: ".activity.SplashActivity"
  5.   dontStopAppOnReset: true
  6.   app: ""
  7.   appium: "http://127.0.0.1:4723/wd/hub"
  8.   automationName: uiautomator2
复制代码
diff报告改进

进行了更好的分类管理. 根据页面进行分类.

目前可以根据老版本的运行结果来断言新版本的老功能是否符合预期.
分为结果对比和数据对比, 降噪还没实现.

支持macaca

之前硬编码了使用老的uiautomator模式, 这次放开了automationName, 可以支持uiautomator2和macaca了
在automationName处可以指定macaca, 其他配置跟appium一样.
  1. androidCapability:
  2.   deviceName: "192.168.0.102:5555"
  3.   appPackage: "com.gotokeep.keep"
  4.   appActivity: ".activity.SplashActivity"
  5.   app: ""
  6.   appium: "http://127.0.0.1:4723/wd/hub"
  7. #  automationName: uiautomator2
  8.   automationName: macaca
  9.   reuse: 3
复制代码
全局断言

用来判断app有没有崩溃, 或者点击后有没有特殊的需要注意的控件
  1. asserts:
  2. - given:
  3.   - //*
  4.   when: []
  5.   then:
  6.   - //*[@package="com.gotokeep.keep"]
  7. - given:
  8.   - //*[@text="发送朋友圈"]
  9.   when: []
  10.   then:
  11.   - //*[@package="com.tencent.mm"]
复制代码
比如设定了断言所有的预期结果里面, 包名都必须是keep, 那么遇到拍照或者发朋友圈, qq登录的地方, 就会提示错误.


可以通过断言预期结果的基本内容.

yaml风格的自动化测试用例原型

完整的自动化用例支持在2.1.0版本再放出来. 目前的只是demo, 只是用来辅助自动遍历的.
  1. testcase:
  2.   name: demo1
  3.   steps:
  4.   - when:
  5.       xpath: //*[contains(@resource-id, 'text_home_train_collection_title')]
  6.       action: driver.swipe(0.5, 0.8, 0.5, 0.2)
  7.     then: []
  8.   - when:
  9.       xpath: //*[contains(@resource-id, 'text_home_train_collection_title')]
  10.       action: driver.swipe(0.5, 0.2, 0.5, 0.8)
  11.     then: []
  12.   - when:
  13.       xpath: //*[contains(@resource-id, 'text_home_train_collection_title')]
  14.       action: tap
  15.     then:
  16.     - //*[contains(@text, "置顶")]
  17.   - when:
  18.       xpath: //*[contains(@text, '置顶')]
  19.       action: click
  20.     then:
  21.     - //*[contains(@text, "添加训练")]
  22.     - //*[contains(@text, "故意错误")]
复制代码
ChangeLog和下版本的计划

目前为2.0.0版本
2.1.0会未发布的下个版本计划
  1. # 2.1.0 [TODO]
  2. 独立的yaml格式的自动化测试用例支持  
  3. 支持从历史数据中寻找最优点击路径  
  4. 支持web  
  5. 支持游戏app遍历  
  6. # 2.0.0
  7. 支持macaca[完成]  
  8. 失败重试[完成]  
  9. 支持简单的测试用例[完成]  
  10. 架构重新设计[完成]
  11. 新老版本对比报告改进[完成]  
  12. # 1.9.0
  13. 支持遍历断言[完成]  
  14. 支持历史对比断言[完成]  
  15. 修正不支持uiautomator2的问题[完成]  
  16. 支持yaml自动化测试用例[完成]  
  17. action支持长按[完成]  
  18. 重构用例生成方式[完成]  
复制代码
完整的配置文件示例


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏
回复

使用道具 举报

该用户从未签到

2#
 楼主| 发表于 2017-6-26 10:40:20 | 只看该作者
  1. ---
  2. logLevel: "TRACE"
  3. reportTitle: "Keep"
  4. saveScreen: true
  5. screenshotTimeout: 20
  6. currentDriver: "android"
  7. showCancel: true
  8. tagLimitMax: 5
  9. tagLimit:
  10. - xpath: //*[../*[@selected='true']]
  11.   count: 12
  12. maxTime: 10800
  13. resultDir: ""
  14. capability:
  15.   newCommandTimeout: 120
  16.   launchTimeout: 120000
  17.   platformVersion: ""
  18.   platformName: "Android"
  19.   autoWebview: "false"
  20.   autoLaunch: "true"
  21.   noReset: "true"
  22.   androidInstallTimeout: 180000
  23. androidCapability:
  24.   deviceName: "192.168.0.102:5555"
  25.   appPackage: "com.gotokeep.keep"
  26.   appActivity: ".activity.SplashActivity"
  27.   dontStopAppOnReset: true
  28.   app: ""
  29.   appium: "http://127.0.0.1:4723/wd/hub"
  30. #  automationName: uiautomator2
  31.   automationName: uiautomator2
  32.   reuse: 3
  33. #  nativeWebScreenshot: "true"
  34. defineUrl:
  35. - //*[@selected='true' and contains(name(), 'TextView')]/@text
  36. #- //*[contains(@resource-id, 'title')]/@text
  37. appWhiteList:
  38. - android
  39. - com.shafa.market
  40. baseUrl:
  41. - ".*MainActivity"
  42. - ".*SNBHomeView.*"
  43. maxDepth: 20
  44. headFirst: true
  45. enterWebView: true
  46. urlBlackList:
  47. - .*OutdoorSummaryMap.*
  48. - .*PersonalPage.*
  49. - .*Training.*
  50. - .*FriendRank.*
  51. - .*\\.base\\.Container.*
  52. #urlWhiteList:
  53. #- ".*Main.*"
  54. backButton:
  55. - //*[contains(@resource-id, "left_button") and @clickable='true']
  56. #defaultBackAction:
  57. #- import sys.process._;
  58. #- Thread.sleep(5000)
  59. #- val name=Seq("adb", "shell", "dumpsys window windows | grep mCurrentFocus").!!.split(" ")(4).split("/")(0)
  60. #- println(s"kill package ${name}")
  61. #- Seq("adb", "shell", s"am force-stop ${name}").!!
  62. #firstList:
  63. #- //*[contains(@resource-id, "layout_picker_view_container"]
  64. selectedList:
  65. #android非空标签
  66. - //*[@clickable='true']
  67. - //*[@clickable='true']//*[contains(name(), 'Text') and string-length(@text)>0 and string-length(@text)<10 ]
  68. #通用的button和image
  69. - //*[@clickable='true']//*[contains(name(), 'Button')]
  70. - //*[@clickable='true']//*[contains(name(), 'Image')]
  71. #todo:如果多个规则都包含相同控件, 如何排序
  72. #处于选中状态的同级控件最后点击
  73. lastList:
  74. - //*[../*[@selected='true']]
  75. - //*[../../*/*[@selected='true']]
  76. - //*[../../*/*[@selected='true'] and contains(@resource-id, 'tab_')]
  77. - //*[contains(name(), "HorizontalScrollView")]
  78. - //*[@resource-id='com.gotokeep.keep:id/layout_bottom']
  79. blackList:
  80. - ".*\\.[0-9].*"
  81. - ".*[0-9]{2,}.*"
  82. - //*[contains(@resource-id, "wrapper_in_custom_title_bar")]//*[contains(@resource-id, "right_button")]
  83. - //*[contains(@resource-id, "share")]
  84. - //*[contains(@text, "开始第")]
  85. - //*[contains(@resource-id, "lock")]
  86. - //*[contains(@text, "举报")]
  87. triggerActions:
  88. - xpath: //*[contains(@resource-id, "layout_picker_view_container")]//*[@text="确定"]
  89. - xpath: //*[contains(@resource-id, "content-wrapper_dialog")]//*[@text="不发了"]
  90. - xpath: //*[@text="拒绝"]
  91. - xpath: //*[@text="放弃"]
  92. - xpath: //*[@text="结束训练"]
  93. - xpath: //*[contains(@resource-id, "quit_confirm_button")]//*[contains(@text, "确定")]
  94. - xpath: //*[contains(@resource-id, "layout_right_second_button")]//*[contains(@resource-id, "right_second_button")]
  95.   action: yoga
  96.   times: 1
  97. asserts:
  98. - given:
  99.   - //*
  100.   then:
  101.   - //*[@package="com.gotokeep.keep"]
  102. - given:
  103.   - //*[@text="胸部"]
  104.   then:
  105.   - //*[contains(@text, "离心俯卧撑")]
  106. testcase:
  107.   name: demo1
  108.   steps:
  109.   - when:
  110.       xpath: //*[contains(@resource-id, 'text_home_train_collection_title')]
  111.       action: driver.swipe(0.5, 0.8, 0.5, 0.2)
  112.     then: []
  113.   - when:
  114.       xpath: //*[contains(@resource-id, 'text_home_train_collection_title')]
  115.       action: driver.swipe(0.5, 0.2, 0.5, 0.8)
  116.     then: []
  117.   - when:
  118.       xpath: //*[contains(@resource-id, 'text_home_train_collection_title')]
  119.       action: tap
  120.     then:
  121.     - //*[contains(@text, "置顶")]
  122.   - when:
  123.       xpath: //*[contains(@text, '置顶')]
  124.       action: click
  125.     then:
  126.     - //*[contains(@text, "添加训练")]
  127.     - //*[contains(@text, "故意错误")]
  128. #所有view的叶子节点 一般表示游戏
  129. #- action: monkey
  130. #  xpath: //android.view.View[not(*) and contains(@bounds, "[0,0]") ]
  131. #  times: 20
  132. #startupActions:
  133. #- println(driver)
  134. #beforeElementAction:
  135. #- xpath: //*[@resource-id="com.shafa.market:id/nav"]//android.widget.TextView
  136. #  action: MiniAppium.event(21)
  137. #- Thread.sleep(3000)
  138. #- println(driver.getPageSource())
  139. #afterElementAction:
  140. #- println(driver)
  141. #afterUrlFinished:
  142. #- monkey()
复制代码
回复 支持 反对

使用道具 举报

  • TA的每日心情
    无聊
    前天 09:07
  • 签到天数: 11 天

    连续签到: 2 天

    [LV.3]测试连长

    4#
    发表于 2017-6-26 14:47:06 | 只看该作者
    赞一个!啥时候用Java或Python重写
    回复 支持 反对

    使用道具 举报

  • TA的每日心情

    1720761397
  • 签到天数: 1 天

    连续签到: 1 天

    5#
    发表于 2017-6-26 14:48:53 | 只看该作者
    人生苦短,请用python,期望来个python版本
    回复 支持 反对

    使用道具 举报

  • TA的每日心情
    无聊
    2024-7-12 13:16
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]测试小兵

    6#
    发表于 2017-6-26 14:49:40 | 只看该作者
    咨询个问题,如果是手机已经有的apk,用那个指令来启动呢,说明,这个apk无法卸载,也无法直接安装新的应用
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    7#
    发表于 2017-6-26 14:51:32 | 只看该作者
    这个不错,我现在公司,也在写遍历测试,算完成50%,一半一半。你这个我使用下。看了文档,就是用例格式的yaml,就是没有类似jason格式解析,比较不好判断哪里出错吧
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    8#
     楼主| 发表于 2017-6-26 15:20:17 | 只看该作者
    乐哈哈yoyo 发表于 2017-6-26 14:49
    咨询个问题,如果是手机已经有的apk,用那个指令来启动呢,说明,这个apk无法卸载,也无法直接安装新的应用

    你估计不懂appium吧, 你可以看看他的文档, 简单来说, capability里面的app参数不写即可.

    回复 支持 反对

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-9-21 05:49 , Processed in 0.069316 second(s), 22 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表