appcrawler介绍
- 一个基于自动遍历的app爬虫工具. 支持android和iOS, 支持真机和模拟器. 最大的特点是灵活性. 可通过配置来设定遍历的规则.
优点
- 跨平台性:
AppCrawler
是基于appium
开发的,所以支持Android
和IOS
- 可控性:对测试的页面,控件类型的选择,测试的深度等都可自由控制
- 可定制:可自定义操作,如输入,滑动等
缺点
- 运行速度较慢:
AppCrawler
是基于appium
开发具备了跨平台的优点,但是也因为这层封装造成了运行速度相对较慢 - 使用门槛高:正因为使用灵活性的问题,也造成了使用门槛的提高,主要基于
yaml
文件中使用appium
的相关技术知识进行配置,这就对使用者有了一定的技术要求
下载与启动
下载
启动
说明:需要 java和appium环境
- step1 :启动appium : appium --session-override
- step2:启动appcrawler :java -jar appcrawler-2.4.0-jar.jar --capability "appPackage=com.taobao.taobao,appActivity=com.taobao.tao.welcome.Welcome" -o result
- 遍历原则:它的遍历原则是,找页面的里层次最深的元素,也就是处于中心位置元素会被优先遍历
- 测试结果:如果没有使用
-o
参数指定log输出的路径,appcrawler
就会在当前目录下生成以时间为命名的文件夹,里面保存了所有的数据,文件、截图、log - 测试报告:在测试log中有一个index.html文件,打开它会看到刚才运行的测试报告
配置文件启动
step1:生成配置文件模板:java -jar appcrawler-2.4.0-jar.jar --demo
- 配置文件demo.yml如下
1. --- 2. pluginList: [] 3. saveScreen: true 4. reportTitle: "" 5. resultDir: "20210307174024" 6. waitLoading: 500 7. waitLaunch: 6000 8. showCancel: true 9. maxTime: 10800 10. maxDepth: 10 11. capability: 12. noReset: "true" 13. fullReset: "false" 14. appium: "http://127.0.0.1:4723/wd/hub" 15. testcase: 16. name: "TesterHome AppCrawler" 17. steps: 18. - given: [] 19. when: null 20. then: [] 21. xpath: "/*" 22. action: "Thread.sleep(5000)" 23. actions: [] 24. times: 0 25. selectedList: 26. - given: [] 27. when: null 28. then: [] 29. xpath: "//*[contains(name(), 'Button')]" 30. action: null 31. actions: [] 32. times: 0 33. - given: [] 34. when: null 35. then: [] 36. xpath: "//*[contains(name(), 'Text') and @clickable='true' and string-length(@text)<10]" 37. action: null 38. actions: [] 39. times: 0 40. - given: [] 41. when: null 42. then: [] 43. xpath: "//*[@clickable='true']/*[contains(name(), 'Text') and string-length(@text)<10]" 44. action: null 45. actions: [] 46. times: 0 47. - given: [] 48. when: null 49. then: [] 50. xpath: "//*[contains(name(), 'Image') and @clickable='true']" 51. action: null 52. actions: [] 53. times: 0 54. - given: [] 55. when: null 56. then: [] 57. xpath: "//*[@clickable='true']/*[contains(name(), 'Image')]" 58. action: null 59. actions: [] 60. times: 0 61. - given: [] 62. when: null 63. then: [] 64. xpath: "//*[contains(name(), 'Image') and @name!='']" 65. action: null 66. actions: [] 67. times: 0 68. - given: [] 69. when: null 70. then: [] 71. xpath: "//*[contains(name(), 'Text') and @name!='' and string-length(@label)<10]" 72. action: null 73. actions: [] 74. times: 0 75. firstList: [] 76. lastList: 77. - given: [] 78. when: null 79. then: [] 80. xpath: "//*[@selected='true']/..//*" 81. action: null 82. actions: [] 83. times: 0 84. - given: [] 85. when: null 86. then: [] 87. xpath: "//*[@selected='true']/../..//*" 88. action: null 89. actions: [] 90. times: 0 91. backButton: 92. - given: [] 93. when: null 94. then: [] 95. xpath: "Navigate up" 96. action: null 97. actions: [] 98. times: 0 99. triggerActions: 100. - given: [] 101. when: null 102. then: [] 103. xpath: "share_comment_guide_btn" 104. action: null 105. actions: [] 106. times: 0 107. xpathAttributes: 108. - "name" 109. - "label" 110. - "value" 111. - "resource-id" 112. - "content-desc" 113. - "instance" 114. - "text" 115. sortByAttribute: 116. - "depth" 117. - "list" 118. - "selected" 119. findBy: "default" 120. defineUrl: [] 121. baseUrl: [] 122. appWhiteList: [] 123. urlBlackList: [] 124. urlWhiteList: [] 125. blackList: 126. - given: [] 127. when: null 128. then: [] 129. xpath: ".*[0-9]{2}.*" 130. action: null 131. actions: [] 132. times: 0 133. beforeRestart: [] 134. beforeElement: 135. - given: [] 136. when: null 137. then: [] 138. xpath: "/*" 139. action: "Thread.sleep(500)" 140. actions: [] 141. times: 0 142. afterElement: [] 143. afterPage: [] 144. afterPageMax: 2 145. tagLimitMax: 2 146. tagLimit: 147. - given: [] 148. when: null 149. then: [] 150. xpath: "确定" 151. action: null 152. actions: [] 153. times: 1000 154. - given: [] 155. when: null 156. then: [] 157. xpath: "取消" 158. action: null 159. actions: [] 160. times: 1000 161. - given: [] 162. when: null 163. then: [] 164. xpath: "share_comment_guide_btn_name" 165. action: null 166. actions: [] 167. times: 1000 168. assertGlobal: []
step2:配置参数
- capability 配置如下
1. capability: 2. noReset: "true" 3. fullReset: "false" 4. appium: "http://127.0.0.1:4723/wd/hub" 5. appPackage: com.taobao.taobao 6. appActivity: com.taobao.tao.welcome.Welcome 7. automationName: uiautomator2 8. autoGrantPermissions: true
testcase: 用于启动APP后的基础测试用例
- given: 所有的先决条件,给定一个条件,只有条件成立的时候才完成后面的操作(实际用的较少)
- when: 先决条件成立后的行为,对什么事件做什么事情
- then: 断言集合,事件结束后对结果断言
1. testcase: 2. name: "TesterHome AppCrawler" 3. steps: 4. - when: 5. xpath: //* 6. action: click 7. - when: 8. xpath: //* 9. action: click 10. then: 11. - //*[contains(@text, '文案')]
action的动作支持
- "" :只是截图记录
- back:后退
- backApp:回退到当前的App,默认等价于back行为 可定制
- monkey:随机事件
- xxx()执行代码:
- Thread.sleep(1000)
- driver.swipe(0.9,0.8,0.9,0.5)
- click:点击事件
- longTap:长按
- 除以上所有行为外均视为输入行为
selectedList:遍历范围设定,设置让其点击所有可点击的TextView
和ImageView
控件,修改完成如下:
1. selectedList: 2. - xpath: //android.widget.ImageView[@clickable='true'] 3. - xpath: //*[@clickable='true' and contains(@class,"Text")]
firstList:优先被点击
lastList:最后执行,设置成点击确定按钮
1. lastList: 2. - { xpath: "//*[text()='确定']", action: click }
- backButton:当所有元素都被点击后默认后退控件定位
- blackList:黑名单
- triggerAction: 特定条件出发执行动作的设置
- agLimitMax: 全局设置,同类型的最多点击的次数;这里设置为2次
tagLimitMax: 2
tagLimit: 自定义控件类型的点击次数,这里设置对于ListView
类型的只点击一次;修改完成如下
- { xpath: "//*[contains(@class, 'List')]//*", times: 1 }
maxDepth: 遍历的最大深度
assertGlobal:设置一个全局断言,例如可设置断言在当前App,如果包名不符合,就可能发生了崩溃,便会报错
配置文件:进入淘宝分类页面
1. --- 2. pluginList: [] 3. saveScreen: true 4. reportTitle: "" 5. resultDir: "20210307174024" 6. waitLoading: 500 7. waitLaunch: 6000 8. showCancel: true 9. maxTime: 10800 10. maxDepth: 10 11. capability: 12. noReset: "true" 13. fullReset: "false" 14. appium: "http://127.0.0.1:4723/wd/hub" 15. appPackage: com.taobao.taobao 16. appActivity: com.taobao.tao.welcome.Welcome 17. automationName: uiautomator2 18. autoGrantPermissions: true 19. testcase: 20. name: "进入分类页面" 21. steps: 22. - given: [] 23. when: null 24. then: [] 25. xpath: "//*[@text='分类']" 26. action: click 27. actions: [] 28. times: 0 29. 30. selectedList: 31. - given: [] 32. when: null 33. then: [] 34. xpath: "//*[contains(name(), 'Button')]" 35. action: null 36. actions: [] 37. times: 0 38. - given: [] 39. when: null 40. then: [] 41. xpath: "//*[contains(name(), 'Text') and @clickable='true' and string-length(@text)<10]" 42. action: null 43. actions: [] 44. times: 0 45. - given: [] 46. when: null 47. then: [] 48. xpath: "//*[@clickable='true']/*[contains(name(), 'Text') and string-length(@text)<10]" 49. action: null 50. actions: [] 51. times: 0 52. - given: [] 53. when: null 54. then: [] 55. xpath: "//*[contains(name(), 'Image') and @clickable='true']" 56. action: null 57. actions: [] 58. times: 0 59. - given: [] 60. when: null 61. then: [] 62. xpath: "//*[@clickable='true']/*[contains(name(), 'Image')]" 63. action: null 64. actions: [] 65. times: 0 66. - given: [] 67. when: null 68. then: [] 69. xpath: "//*[contains(name(), 'Image') and @name!='']" 70. action: null 71. actions: [] 72. times: 0 73. - given: [] 74. when: null 75. then: [] 76. xpath: "//*[contains(name(), 'Text') and @name!='' and string-length(@label)<10]" 77. action: null 78. actions: [] 79. times: 0 80. firstList: [] 81. lastList: 82. - given: [] 83. when: null 84. then: [] 85. xpath: "//*[@selected='true']/..//*" 86. action: null 87. actions: [] 88. times: 0 89. - given: [] 90. when: null 91. then: [] 92. xpath: "//*[@selected='true']/../..//*" 93. action: null 94. actions: [] 95. times: 0 96. backButton: 97. - given: [] 98. when: null 99. then: [] 100. xpath: "Navigate up" 101. action: null 102. actions: [] 103. times: 0 104. triggerActions: 105. - given: [] 106. when: null 107. then: [] 108. xpath: 109. action: 110. actions: [] 111. times: 0 112. xpathAttributes: 113. - "name" 114. - "label" 115. - "value" 116. - "resource-id" 117. - "content-desc" 118. - "instance" 119. - "text" 120. sortByAttribute: 121. - "depth" 122. - "list" 123. - "selected" 124. findBy: "default" 125. defineUrl: [] 126. baseUrl: [] 127. appWhiteList: [] 128. urlBlackList: [] 129. urlWhiteList: [] 130. blackList: 131. - given: [] 132. when: null 133. then: [] 134. xpath: ".*[0-9]{2}.*" 135. action: null 136. actions: [] 137. times: 0 138. beforeRestart: [] 139. beforeElement: 140. - given: [] 141. when: null 142. then: [] 143. xpath: "/*" 144. action: "Thread.sleep(500)" 145. actions: [] 146. times: 0 147. afterElement: [] 148. afterPage: [] 149. afterPageMax: 2 150. tagLimitMax: 2 151. tagLimit: 152. - given: [] 153. when: null 154. then: [] 155. xpath: "È·¶¨" 156. action: null 157. actions: [] 158. times: 1000 159. - given: [] 160. when: null 161. then: [] 162. xpath: "È¡Ïû" 163. action: null 164. actions: [] 165. times: 1000 166. - given: [] 167. when: null 168. then: [] 169. xpath: "share_comment_guide_btn_name" 170. action: null 171. actions: [] 172. times: 1000 173. assertGlobal: []
step3:配置文件启动:java -jar appcrawler-2.4.0-jar.jar -c demo.yml