AppCrawler AppCrawler 自动遍历工具 2.0 版本发布

思寒_seveniruby · 2017年04月19日 · 最后由 silver 回复于 2020年11月02日 · 55 次阅读
本帖已被设为精华帖!

2.1.0 版本已经发布

获取方式

百度网盘: https://pan.baidu.com/s/1bpmR3eJ
在线帮助文档: https://seveniruby.gitbooks.io/appcrawler/content/
相关文章: https://testerhome.com/search?q=appCrawler
腾讯安全部门也有使用 https://security.tencent.com/index.php/blog/msg/105

问答 QQ 群:177933995 能获取最新的内测版本和一些配置文件模板
为了表示对社区 7 月 15 号的测试大会的支持, 接下来将只允许参会同学加群咨询问题
加群请注明参会的个人姓名 大会报名连接

自动遍历的价值

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

截图

使用介绍


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


Usage: appcrawler [options]

  -a, --app <value>        Android或者iOS的文件地址, 可以是网络地址, 赋值给appium的app选项
  -c, --conf <value>       配置文件地址
  -p, --platform <value>   平台类型android或者ios, 默认会根据app后缀名自动判断
  -t, --maxTime <value>    最大运行时间. 单位为秒. 超过此值会退出. 默认最长运行3个小时
  -u, --appium <value>     appium的url地址
  -o, --output <value>     遍历结果的保存目录. 里面会存放遍历生成的截图, 思维导图和日志
  --capability k1=v1,k2=v2...
                           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信息
  --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

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

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

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

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

#根据wda的inspector生成测试用例代码
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

androidCapability:
  deviceName: "192.168.0.102:5555"
  appPackage: "com.gotokeep.keep"
  appActivity: ".activity.SplashActivity"
  dontStopAppOnReset: true
  app: ""
  appium: "http://127.0.0.1:4723/wd/hub"
  automationName: uiautomator2

diff 报告改进

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

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

支持 macaca

之前硬编码了使用老的 uiautomator 模式, 这次放开了 automationName, 可以支持 uiautomator2 和 macaca 了
在 automationName 处可以指定 macaca, 其他配置跟 appium 一样.

androidCapability:
  deviceName: "192.168.0.102:5555"
  appPackage: "com.gotokeep.keep"
  appActivity: ".activity.SplashActivity"
  app: ""
  appium: "http://127.0.0.1:4723/wd/hub"
#  automationName: uiautomator2
  automationName: macaca
  reuse: 3

全局断言

用来判断 app 有没有崩溃, 或者点击后有没有特殊的需要注意的控件

asserts:
- given:
  - //*
  when: []
  then:
  - //*[@package="com.gotokeep.keep"]
- given:
  - //*[@text="发送朋友圈"]
  when: []
  then:
  - //*[@package="com.tencent.mm"]

比如设定了断言所有的预期结果里面, 包名都必须是 keep, 那么遇到拍照或者发朋友圈, qq 登录的地方, 就会提示错误.


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

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

完整的自动化用例支持在 2.1.0 版本再放出来. 目前的只是 demo, 只是用来辅助自动遍历的.

testcase:
  name: demo1
  steps:
  - when:
      xpath: //*[contains(@resource-id, 'text_home_train_collection_title')]
      action: driver.swipe(0.5, 0.8, 0.5, 0.2)
    then: []
  - when:
      xpath: //*[contains(@resource-id, 'text_home_train_collection_title')]
      action: driver.swipe(0.5, 0.2, 0.5, 0.8)
    then: []
  - when:
      xpath: //*[contains(@resource-id, 'text_home_train_collection_title')]
      action: tap
    then:
    - //*[contains(@text, "置顶")]
  - when:
      xpath: //*[contains(@text, '置顶')]
      action: click
    then:
    - //*[contains(@text, "添加训练")]
    - //*[contains(@text, "故意错误")]

ChangeLog 和下版本的计划

目前为 2.0.0 版本
2.1.0 会未发布的下个版本计划

# 2.1.0 [TODO]
独立的yaml格式的自动化测试用例支持  
支持从历史数据中寻找最优点击路径  
支持web  
支持游戏app遍历  
# 2.0.0
支持macaca[完成]  
失败重试[完成]  
支持简单的测试用例[完成]  
架构重新设计[完成] 
新老版本对比报告改进[完成]  
# 1.9.0
支持遍历断言[完成]  
支持历史对比断言[完成]  
修正不支持uiautomator2的问题[完成]  
支持yaml自动化测试用例[完成]  
action支持长按[完成]  
重构用例生成方式[完成]  

完整的配置文件示例

---
logLevel: "TRACE"
reportTitle: "Keep"
saveScreen: true
screenshotTimeout: 20
currentDriver: "android"
showCancel: true
tagLimitMax: 5
tagLimit:
- xpath: //*[../*[@selected='true']]
  count: 12
maxTime: 10800
resultDir: ""
capability:
  newCommandTimeout: 120
  launchTimeout: 120000
  platformVersion: ""
  platformName: "Android"
  autoWebview: "false"
  autoLaunch: "true"
  noReset: "true"
  androidInstallTimeout: 180000
androidCapability:
  deviceName: "192.168.0.102:5555"
  appPackage: "com.gotokeep.keep"
  appActivity: ".activity.SplashActivity"
  dontStopAppOnReset: true
  app: ""
  appium: "http://127.0.0.1:4723/wd/hub"
#  automationName: uiautomator2
  automationName: uiautomator2
  reuse: 3
#  nativeWebScreenshot: "true"
defineUrl:
- //*[@selected='true' and contains(name(), 'TextView')]/@text
#- //*[contains(@resource-id, 'title')]/@text
appWhiteList:
- android
- com.shafa.market
baseUrl:
- ".*MainActivity"
- ".*SNBHomeView.*"
maxDepth: 20
headFirst: true
enterWebView: true
urlBlackList:
- .*OutdoorSummaryMap.*
- .*PersonalPage.*
- .*Training.*
- .*FriendRank.*
- .*\\.base\\.Container.*
#urlWhiteList:
#- ".*Main.*"
backButton:
- //*[contains(@resource-id, "left_button") and @clickable='true']
#defaultBackAction:
#- import sys.process._;
#- Thread.sleep(5000)
#- val name=Seq("adb", "shell", "dumpsys window windows | grep mCurrentFocus").!!.split(" ")(4).split("/")(0)
#- println(s"kill package ${name}")
#- Seq("adb", "shell", s"am force-stop ${name}").!!
#firstList:
#- //*[contains(@resource-id, "layout_picker_view_container"]
selectedList:
#android非空标签
- //*[@clickable='true']
- //*[@clickable='true']//*[contains(name(), 'Text') and string-length(@text)>0 and string-length(@text)<10 ]
#通用的button和image
- //*[@clickable='true']//*[contains(name(), 'Button')]
- //*[@clickable='true']//*[contains(name(), 'Image')]
#todo:如果多个规则都包含相同控件, 如何排序
#处于选中状态的同级控件最后点击
lastList:
- //*[../*[@selected='true']]
- //*[../../*/*[@selected='true']]
- //*[../../*/*[@selected='true'] and contains(@resource-id, 'tab_')]
- //*[contains(name(), "HorizontalScrollView")]
- //*[@resource-id='com.gotokeep.keep:id/layout_bottom']
blackList:
- ".*\\.[0-9].*"
- ".*[0-9]{2,}.*"
- //*[contains(@resource-id, "wrapper_in_custom_title_bar")]//*[contains(@resource-id, "right_button")]
- //*[contains(@resource-id, "share")]
- //*[contains(@text, "开始第")]
- //*[contains(@resource-id, "lock")]
- //*[contains(@text, "举报")]
triggerActions:
- xpath: //*[contains(@resource-id, "layout_picker_view_container")]//*[@text="确定"]
- xpath: //*[contains(@resource-id, "content-wrapper_dialog")]//*[@text="不发了"]
- xpath: //*[@text="拒绝"]
- xpath: //*[@text="放弃"]
- xpath: //*[@text="结束训练"]
- xpath: //*[contains(@resource-id, "quit_confirm_button")]//*[contains(@text, "确定")]
- xpath: //*[contains(@resource-id, "layout_right_second_button")]//*[contains(@resource-id, "right_second_button")]
  action: yoga
  times: 1
asserts:
- given:
  - //*
  then:
  - //*[@package="com.gotokeep.keep"]
- given:
  - //*[@text="胸部"]
  then:
  - //*[contains(@text, "离心俯卧撑")]
testcase:
  name: demo1
  steps:
  - when:
      xpath: //*[contains(@resource-id, 'text_home_train_collection_title')]
      action: driver.swipe(0.5, 0.8, 0.5, 0.2)
    then: []
  - when:
      xpath: //*[contains(@resource-id, 'text_home_train_collection_title')]
      action: driver.swipe(0.5, 0.2, 0.5, 0.8)
    then: []
  - when:
      xpath: //*[contains(@resource-id, 'text_home_train_collection_title')]
      action: tap
    then:
    - //*[contains(@text, "置顶")]
  - when:
      xpath: //*[contains(@text, '置顶')]
      action: click
    then:
    - //*[contains(@text, "添加训练")]
    - //*[contains(@text, "故意错误")]
#所有view的叶子节点 一般表示游戏
#- action: monkey
#  xpath: //android.view.View[not(*) and contains(@bounds, "[0,0]") ]
#  times: 20
#startupActions:
#- println(driver)
#beforeElementAction:
#- xpath: //*[@resource-id="com.shafa.market:id/nav"]//android.widget.TextView
#  action: MiniAppium.event(21)
#- Thread.sleep(3000)
#- println(driver.getPageSource())
#afterElementAction:
#- println(driver)
#afterUrlFinished:
#- monkey()

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 183 条回复 时间 点赞

不错不错

—— 来自 TesterHome 官方 安卓客户端

@seveniruby 刚使用 AppCrawler 想问问思寒老师, 如果启动 appium-desktop 是否也可以?

赞一个!啥时候用 Java 或 Python 重写😅

Mingway_Hu 回复

哈哈,好问题。

刘晓光 回复

哈哈. 谜之尴尬. 期待有同学搞出来 java 版本吧. java 的生态还是健全的.

我想参与 java 版

Young 回复

@skytraveler 要不大家一起搞个 java 版本吧. 我提供技术指导. 搞个社区的开源项目

@seveniruby 你的百度网盘里 只见到了 2.0 jar 包版,有 zip 解压 bin 的版本吗 还未打包弄到网盘么?

赞成,你把架构框架搞一下 大家一起来做搬运工

恒温 回复

找个人带头吧

给力,期待 AppCrawler 越多越好

源码 github 上也放一份

+1 期待 python 版本的。

超级期待 2.1.0 的游戏 app 遍历

python 需要帮忙,算我一个

Python 的话,也算我一个

期待 python + 10086

21楼 已删除

厉害了

23楼 已删除

@seveniruby appcrawler 生成的图片实际格式是 png 的,但是用了 jpg 后缀,能不能改一下呢?毕竟 jpg 写死在代码里面了,改成可配置也行

lsy 回复

可以 下次更新带上去吧

java+10086

配置:afterElementAction:println(driver) 老是有这个问题。

@seveniruby 2.0 版本的 解压 bin 版本 可以打包一个么? 另外 2.0 支持 appium 1.6.4 么?

期待 python 版本的。

期待 python 版本的

咨询个问题,如果是手机已经有的 apk,用那个指令来启动呢,说明,这个 apk 无法卸载,也无法直接安装新的应用

—— 来自 TesterHome 官方 安卓客户端

乐乐猪 回复

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

小马 回复

以后都直接通过 jar 包方式提供了. 直接 java -jar 运行即可. bin 格式的, 很多人不会用. 我就不提供了

思寒_seveniruby 将本帖设为了精华贴 04月25日 06:26

java 包 要运行 conf 的话 怎么弄。。。 自己新建个 conf 目录 新建.yaml 文件 在 jar 包同一目录下么?

小马 回复

随便, 只要 yaml 文件地址路径传给 appcrawler 即可.

  • 在生成报告的 web 页面(index.html)中有这样的错误:
Message:    文件提前结束。
Exception:  org.xml.sax.SAXParseException
com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source)
com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source)
javax.xml.parsers.DocumentBuilder.parse(Unknown Source)
com.xueqiu.qa.appcrawler.RichData$.toDocument(RichData.scala:26)
com.xueqiu.qa.appcrawler.TemplateTestCase$$anonfun$addTestCase$1$$anonfun$apply$3.apply(TemplateTestCase.scala:65)
org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85)
org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104)
org.scalatest.Transformer.apply(Transformer.scala:22)
org.scalatest.Transformer.apply(Transformer.scala:20)
org.scalatest.FunSuiteLike$$anon$1.apply(FunSuiteLike.scala:186)
org.scalatest.TestSuite$class.withFixture(TestSuite.scala:196)
org.scalatest.FunSuite.withFixture(FunSuite.scala:1560)
  • 生成报告目录下 appcrawler.log 中我看有一段:
2017-04-25 16:34:04 INFO [Crawler.setElementAction.661] set action to back
2017-04-25 16:34:04 INFO [Crawler.getBackButton.670] go back
2017-04-25 16:34:04 WARN [Crawler.getBackButton.687] find back button error
2017-04-25 16:34:04 INFO [Crawler.setElementAction.661] set action to back
2017-04-25 16:34:04 INFO [Crawler.crawl.813] skip beforeElementAction
2017-04-25 16:34:04 INFO [Crawler.doElementAction.966] current element = com.xxx.xxx.MainListPresenter_Back-16
2017-04-25 16:34:04 INFO [Crawler.doElementAction.967] current index = 15
2017-04-25 16:34:04 INFO [Crawler.doElementAction.968] current action = back
2017-04-25 16:34:04 INFO [Crawler.doElementAction.969] current url = com.xxx.xxx-MainListPresenter
2017-04-25 16:34:04 INFO [Crawler.doElementAction.970] current xpath = Back-16
2017-04-25 16:34:04 INFO [Crawler.doElementAction.971] current tag path = com.xxx.xxx-MainListPresenter_Back-16
2017-04-25 16:34:04 INFO [Crawler.doElementAction.972] current file name = com.xxx.xxx-MainListPresenter_
2017-04-25 16:34:04 INFO [Crawler.doElementAction.973] current uri = com.xxx.xxx-MainListPresenter  Back-16         
2017-04-25 16:34:04 WARN [Crawler.back.1057] two back action too close

请问下大神 ,我遍历我们 apk 时,在某一个页面停留一会就返回直接返回首页,看报告中有上面的异常信息,这可能是什么错误呢?

liwei 回复

别喊大神. 直接喊名字即可 提示异常的表示没有截取到当时点击后的 page source, 这个就仔细分析了. 肯定是没有正确的遍历导致的.

😀 那这个是工具的问题吗? 因为我就直接运行

java -jar D:\worktools\appcrawler-2.0.0.jar --capability appPackage=,appActivity=

有什么解决办法吗?

没明白怎么使用,是在编写 appium 的测试代码的时候加入那些配置?有没有详细的示例或者文档,看了在线文档,没明白要怎么用

👍 坐等 2.1🏃 🏃 🏃

请问支持 WEBVIEW 吗?

赞一个 . 看到写后面还要用 kotlin, 特地去 google 了一把这个是啥, 哈哈.

配置文件指定了账号和密码,但是登录进去了主界面之后,点了两个导航按钮,就退出了,执行结束。不知道是不是自己的配置文件写的有些问题。

在哪里能看插件怎么写呢?我没有找到啊

思寒,html 报告在浏览器打开后图片显示不出来....,在报告的文件夹里图片都是正常显示的

好吧,图片没显示出来是因为浏览器的问题,在 chrome 正常,在 edge 和 ie11 显示不出来

这个不错,我现在公司,也在写遍历测试,算完成 50%,一半一半。你这个我使用下。看了文档,就是用例格式的 yaml,就是没有类似 jason 格式解析,比较不好判断哪里出错吧

Exception in thread "main" org.openqa.selenium.SessionNotCreatedException: A new session could not be created. Details: Appium's IosDriver does not support xcode version 8.3.1. Apple has deprecated UIAutomation. Use the "XCUITest" automationName capability instead. (WARNING: The server did not provide any stacktrace information) 启动 appium1.6.4beta 运行 appcrawler 有什么办法解决吗 ? @seveniruby 思寒老师

Ben 回复

答案就在你贴的错误提示里 今天群里也有人反馈这个 他自己自行解决了

我知道是 Use the "XCUITest" automationName capability instead 但是还没有思路 😔

{ "platformName": "IOS", "platformVersion": "10.3", "bundleId": "com.banmatripDev", "deviceName": "iPhone 7", "udid": "12c601be16806322be50d9d0318f3f0f7710139c", "automationName": "XCUITest" } 结果还是这样滴 😂

Ben 回复

你这个是从什么地方配置的, 目前的配置是 yaml 格式吧.

遍历过程中有没有做 ANR CRASH 闪退的检查点

俊俊陈 回复

自己写规则断言就行

你好,我想问下,我用了-o,思维导图是日志中的哪个文件啊?

@seveniruby 发现 如果 每次都是用 -o result/ 来指定结果保存目录的话,jpg xml dom 等只是会追加到该目录下,不覆盖以前的结果记录。但是这个 index.html 确是每次都覆盖替换为最新结果的。 结果导致以往的 index 关联资源就不可查了。

小马 回复

你还是换目录名字吧. 重复覆盖这个不能保证总是追加. 对结果的 merge 我以后再支持.

我想问下 带脚本的怎么运行啊 appcrawler -c conf/xueqiu.json -p android -o result/ 有没有带配置 带脚本运行的 怎么弄? 例如登录脚本

使用 pagesource 可以获取到 WebView 内 H5 控件信息吗

pagesource 可以导出不可视控件么?

马着学习,谢谢。

你好,可以指定点击哪些控件吗,因为现在所有的都点击,执行速度有些慢,如果可以的话是怎么指定?谢谢!

66楼 已删除

@seveniruby 请问 yaml 配置文件里的参数有具体说明文档吗?网盘里的视频和在线帮助文档没有具体的说明。defineUrl 和 baseUrl 不理解,一开始没配置就报错了,后来发现是必填的。。。

AlexSun 回复

mark 下. 下个版本解决. 这的确是个问题. 配置文件我更新到帖子里了

这个 “完整” 有多完整? 包含了 appcrawler 可以支持的全部定制参数么? 能整理个参数的文字说明不? 或者源码里可以查到可被使用的参数的吧,求指教源码哪个路径下存放了 appcrawler 的自定义可配置参数定义的?

小马 回复

CrawlerConf.scala 文件

有段时间没看,都到 2.0 版本了,收藏下回头看

@seveniruby 我的 yml 是这么配置的,但是跑起来并不生效还是会点击相应的列表内容。这是怎么回事儿。字段变了吗?

blackList:
- ".*下载.*"
- ".*发现.*"
- "升级"

有人遇到过下面这个错误吗?密码输入完后输入法界面一直在,没有隐藏,登陆不了。而账号输入之后就会隐藏起来。

2017-05-05 14:32:36 INFO [Crawler.doElementAction.1005] need input zxcvbn
2017-05-05 14:32:36 INFO [AppiumClient.findElementByUrlElement.378] find by xpath= //*[@resource-id="android:id/content"]/*[@resource-id="com.honeywell.iaq:id/activity_login"]/*[@resource-id="com.honeywell.iaq:id/ll_group"]/*[@resource-id="com.honeywell.iaq:id/password"]
2017-05-05 14:32:36 INFO [AppiumClient.retry.162] retry execute success
2017-05-05 14:32:36 INFO [AppiumClient.findElementByUrlElement.384] find by xpath success
2017-05-05 14:32:36 INFO [Crawler.doElementAction.1012] mark android_20170505143131/5_com.honeywell.iaq-LoginActivity_content-activity_login-ll_group-phone_number.ori.jpg to android_20170505143131/5_com.honeywell.iaq-LoginActivity_content-activity_login-ll_group-phone_number.ps.jpg
2017-05-05 14:32:36 INFO [AppiumClient.mark.243] platformName=android
2017-05-05 14:32:36 INFO [AppiumClient.mark.244] getScreenshot
2017-05-05 14:32:36 INFO [AppiumClient.mark.257] write png android_20170505143131/5_com.honeywell.iaq-LoginActivity_content-activity_login-ll_group-phone_number.ori.jpg
2017-05-05 14:32:36 INFO [Crawler.apply.1027] input zxcvbn
2017-05-05 14:32:42 WARN [AppiumClient.retry.166] message=An unknown server-side error occurred while processing the command. Original error: Soft keyboard not present, cannot hide keyboard (WARNING: The server did not provide any stacktrace information)

Ben 回复

你好,请问你的问题解决啦么

@seveniruby 请问这是什么问题,我没有加配置文件直接跑的

怎么做游戏的自动化遍历,有没有思路或者方案?请指点!!! 1,非 sikuli 的那种方案,sikuli 需要提前记录截图,然后在做点击输入,这种并不是自动化遍历 2,用 ocr 识别按钮文字,在做点击,ocr 本身识别率不高,切较难做到

十分期待下个版本,😁

@seveniruby ,请问一下,如果点击过程中退出了 app,如何配置再进入呢?或者是调到了其他 app,比如充值,如何再配置回到被测 app 呢?

能否分享下设计思路、我想试试整个 python 版本的, 最近正在搞 tensorflow 想做个自动遍历 UI 的东东,结果发现楼主这直接有了。 PS:没在北京参加不了 715 大会进不了 QQ 群好忧桑- -

Jayvee 回复

那个是答疑群. 只服务对社区有帮助的同学, 你申请的时候附上一些你帮助过社区的事情也可以加进去的.

@seveniruby 执行遍历一段时间后,instruments 进程达到了 3 个多 G。请问这个是什么原因导致的,能否优化呢。

@seveniruby appcrawler 控制台乱码怎么解决

error: Failed to start an Appium session, err was: Error: Command failed: C:\windows\system32\cmd.exe /s /c "E:\software\4.2_SDK\android-sdk-new_4.2\android-sdk-new\platform-tools\adb.exe -s 0123456789ABCDEF shell "ps 'uiautomator'"" @seveniruby android N 上不支持这么查找 uiautomator process 啊?怎么破?

fiona 回复

这是 appium 的问题, 跟 AppCrawler 无关. appium 新版本会去解决这个问题的. 或者你自己定制下 appium

如果使用 macaca 还是要依赖 appium 吗?

 appium: "http://127.0.0.1:4723/wd/hub"
#  automationName: uiautomator2
  automationName: macaca

appium 填写 macaca 的 url 吗? @seveniruby

@seveniruby yaml 文件的具体配置有没有说明文档啊 我这边配置完运行 报出 null pointer exception 异常

weiweiliu 回复

有限选项需要给默认值 比如 [] 如果什么都不写都是 null 这个我也注意了 下个版本会彻底修复

期待 python 版本的

期待 python 版 +1

@seveniruby 请问下如何在 yaml 配置文件中 startupActions 中配置去点击某个 id 的控件(已知控件的 id)

@seveniruby 你好 我使用 2.0.1 的 jar java -jar appcrawler-2.0.1.jar -c 123.yml -a guahao.apk 遇到下面错误 应该解决?

2017-06-06 15:51:47 ERROR [AppiumClient.asyncTask.149] exception 2017-06-06 15:51:47 ERROR [AppiumClient.asyncTask.150] org.openqa.selenium.WebDriverException: An unknown server-side error occurred while processing the command. (WARNING: The server did not provide any stacktrace information) Command duration or timeout: 71 milliseconds Build info: version: 'unknown', revision: 'unknown', time: 'unknown' System info: host: 'LAPTOP-38CHF3G1', ip: '192.168.118.213', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_91' Driver info: io.appium.java_client.android.AndroidDriver Capabilities [{appPackage=com.greenline.guahao, reuse=3, noReset=true, dontStopAppOnReset=true, deviceName=c1661029, platform=LINUX, androidInstallTimeout=180000, desired={app=D:\WorkSpace\appcrawler\appcrawler-1.7.1\bin\guahao.apk, appPackage=com.greenline.guahao, reuse=3, appium=http://127.0.0.1:4723/wd/hub, noReset=true, dontStopAppOnReset=true, deviceName=192.168.0.102:5555, launchTimeout=120000, appActivity=.home.HomeActivity, androidInstallTimeout=180000, newCommandTimeout=120, autoLaunch=true, platformVersion=, automationName=uiautomator2, autoWebview=false, platformName=Android}, newCommandTimeout=120, platformVersion=5.0.2, webStorageEnabled=false, automationName=uiautomator2, browserName=Android, takesScreenshot=true, javascriptEnabled=true, autoWebview=false, platformName=Android, app=D:\WorkSpace\appcrawler\appcrawler-1.7.1\bin\guahao.apk, networkConnectionEnabled=true, appium=http://127.0.0.1:4723/wd/hub, warnings={}, databaseEnabled=false, launchTimeout=120000, appActivity=.home.HomeActivity, autoLaunch=true, locationContextEnabled=false}] Session ID: 01e3d0b8-e106-4edc-bb91-7a8d7c8366d8 2017-06-06 15:51:47 ERROR [AppiumClient.asyncTask.151] java.util.concurrent.FutureTask.report(Unknown Source) java.util.concurrent.FutureTask.get(Unknown Source) com.xueqiu.qa.appcrawler.WebDriver$$anonfun$2.apply(WebDriver.scala:134) scala.util.Try$.apply(Try.scala:192) com.xueqiu.qa.appcrawler.WebDriver$class.asyncTask(WebDriver.scala:125) com.xueqiu.qa.appcrawler.AppiumClient.asyncTask(AppiumClient.scala:28) com.xueqiu.qa.appcrawler.AppiumClient$$anonfun$getPageSource$1.apply$mcVI$sp(AppiumClient.scala:307) scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:166) com.xueqiu.qa.appcrawler.AppiumClient.getPageSource(AppiumClient.scala:306) com.xueqiu.qa.appcrawler.Crawler.refreshPage(Crawler.scala:525) com.xueqiu.qa.appcrawler.Crawler.runStartupScript(Crawler.scala:205) com.xueqiu.qa.appcrawler.Crawler.start(Crawler.scala:139) com.xueqiu.qa.appcrawler.AppCrawler$.startCrawl(AppCrawler.scala:313) com.xueqiu.qa.appcrawler.AppCrawler$.main(AppCrawler.scala:303) com.xueqiu.qa.appcrawler.AppCrawler.main(AppCrawler.scala) Exception in thread "main" java.lang.NullPointerException at scala.collection.immutable.StringOps$.length$extension(StringOps.scala:48) at scala.collection.immutable.StringOps.length(StringOps.scala:48) at scala.collection.IndexedSeqOptimized$class.isEmpty(IndexedSeqOptimized.scala:27) at scala.collection.immutable.StringOps.isEmpty(StringOps.scala:30) at scala.collection.TraversableOnce$class.nonEmpty(TraversableOnce.scala:109) at scala.collection.immutable.StringOps.nonEmpty(StringOps.scala:30) at com.xueqiu.qa.appcrawler.Crawler.refreshPage(Crawler.scala:528) at com.xueqiu.qa.appcrawler.Crawler.runStartupScript(Crawler.scala:205) at com.xueqiu.qa.appcrawler.Crawler.start(Crawler.scala:139) at com.xueqiu.qa.appcrawler.AppCrawler$.startCrawl(AppCrawler.scala:313) at com.xueqiu.qa.appcrawler.AppCrawler$.main(AppCrawler.scala:303) at com.xueqiu.qa.appcrawler.AppCrawler.main(AppCrawler.scala)

想问下 startupActions 被注释掉了,是已经不能用了吗,如果可以继续用的话,想要实现查找某个控件并点击应该怎么写,我试了用 driver.findElement(By.XX).click() 或者 see().tap() 不行了

Ps:我们应用启动页和登录页都是 LoginActivity,并且 debug 包在启动页会有一个弹窗要求选择进入什么环境。现在遇到了一个问题就是在启动页点击选择服务器后进入登录页后,说是所有 element 都被点击了,然后找不到返回键,结果就直接退出应用,不知道有没人有类似情景,这个应该怎么处理呢

雪怪 回复

新版本推荐用 testcase 配置项

94楼 已删除

原来如此,改成用 testcase 配置就成功了,多谢~

我与你遇到一样的问题,请问你解决了吗

测试 ios get page source success 但是抛出下面的错误,问题出在哪?有遇到这种情况的解答一下 急急急

xue 回复

还没有😂 😂 😂 😂 😂

用 2.1 版本试试

谢谢你的解答! 之前的问题是解决了, 执行一段时间后报了新的错误 日志里有生成 132_com.greenline.guahao-HomeActivity_android.view.View-android.widget.ListView-android.view.View-javascript 这个文件,但是空的

2017-06-21 13:59:38 INFO [AppiumClient.mark.237] read from Android_20170621135043/132_com.greenline.guahao-HomeActivity_android.view.View-android.widget.ListView-android.view.View-javascript:;-android.view.View.clicked.png 2017-06-21 13:59:38 ERROR [Crawler.crawl.196] crawl not finish, return with exception 2017-06-21 13:59:38 ERROR [Crawler.crawl.197] Can't read input file! 2017-06-21 13:59:38 ERROR [Crawler.crawl.198] IIOException: Can't read input file! 2017-06-21 13:59:38 ERROR [Crawler.crawl.199] 2017-06-21 13:59:38 ERROR [Crawler.apply.200] javax.imageio.IIOException: Can't read input file! 2017-06-21 13:59:38 ERROR [Crawler.apply.200] at javax.imageio.ImageIO.read(Unknown Source) 2017-06-21 13:59:38 ERROR [Crawler.apply.200] at com.testerhome.appcrawler.driver.AppiumClient.mark(AppiumClient.scala:238) 2017-06-21 13:59:38 ERROR [Crawler.apply.200] at com.testerhome.appcrawler.Crawler.doElementAction(Crawler.scala:992) 2017-06-21 13:59:38 ERROR [Crawler.apply.200] at com.testerhome.appcrawler.Crawler.crawl(Crawler.scala:797) 2017-06-21 13:59:38 ERROR [Crawler.apply.200] at com.testerhome.appcrawler.Crawler$$anonfun$1.apply$mcV$sp(Crawler.scala:173) 2017-06-21 13:59:38 ERROR [Crawler.apply.200] at com.testerhome.appcrawler.Crawler$$anonfun$1.apply(Crawler.scala:173) 2017-06-21 13:59:38 ERROR [Crawler.apply.200] at com.testerhome.appcrawler.Crawler$$anonfun$1.apply(Crawler.scala:173) 2017-06-21 13:59:38 ERROR [Crawler.apply.200] at scala.util.Try$.apply(Try.scala:192) 2017-06-21 13:59:38 ERROR [Crawler.apply.200] at com.testerhome.appcrawler.Crawler.crawl(Crawler.scala:173) 2017-06-21 13:59:38 ERROR [Crawler.apply.200] at com.testerhome.appcrawler.Crawler.start(Crawler.scala:157) 2017-06-21 13:59:38 ERROR [Crawler.apply.200] at com.testerhome.appcrawler.AppCrawler$.startCrawl(AppCrawler.scala:342) 2017-06-21 13:59:38 ERROR [Crawler.apply.200] at com.testerhome.appcrawler.AppCrawler$.parseParams(AppCrawler.scala:310) 2017-06-21 13:59:38 ERROR [Crawler.apply.200] at com.testerhome.appcrawler.AppCrawler$.main(AppCrawler.scala:90) 2017-06-21 13:59:38 ERROR [Crawler.apply.200] at com.testerhome.appcrawler.AppCrawler.main(AppCrawler.scala) 2017-06-21 13:59:38 ERROR [Crawler.crawl.201] create new session 2017-06-21 13:59:38 INFO [Crawler.restart.216] restart appium 2017-06-21 13:59:38 INFO [Crawler.restart.218] set app to null to restart appium 2017-06-21 13:59:38 INFO [Crawler.setupAppium.253] use AppiumClient Exception in thread "main" org.openqa.selenium.SessionNotCreatedException: A new session could not be created. (Original error: Requested a new session but one was in progress) (WARNING: The server did not provide any stacktrace information) Command duration or timeout: 748 milliseconds Build info: version: 'unknown', revision: 'unknown', time: 'unknown' System info: host: 'LAPTOP-38CHF3G1', ip: '192.168.118.213', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '1.8.0_91' Driver info: io.appium.java_client.android.AndroidDriver at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) at java.lang.reflect.Constructor.newInstance(Unknown Source) at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:206) at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:158) at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:678) at io.appium.java_client.DefaultGenericMobileDriver.execute(DefaultGenericMobileDriver.java:40) at io.appium.java_client.AppiumDriver.execute(AppiumDriver.java:1) at io.appium.java_client.android.AndroidDriver.execute(AndroidDriver.java:1) at org.openqa.selenium.remote.RemoteWebDriver.startSession(RemoteWebDriver.java:249) at org.openqa.selenium.remote.RemoteWebDriver.(RemoteWebDriver.java:131) at org.openqa.selenium.remote.RemoteWebDriver.(RemoteWebDriver.java:144) at io.appium.java_client.DefaultGenericMobileDriver.(DefaultGenericMobileDriver.java:36) at io.appium.java_client.AppiumDriver.(AppiumDriver.java:114) at io.appium.java_client.AppiumDriver.(AppiumDriver.java:132) at io.appium.java_client.android.AndroidDriver.(AndroidDriver.java:92) at com.testerhome.appcrawler.driver.AppiumClient.appium(AppiumClient.scala:160) at com.testerhome.appcrawler.driver.AppiumClient.(AppiumClient.scala:38) at com.testerhome.appcrawler.Crawler.setupAppium(Crawler.scala:254) at com.testerhome.appcrawler.Crawler.restart(Crawler.scala:220) at com.testerhome.appcrawler.Crawler.crawl(Crawler.scala:204) at com.testerhome.appcrawler.Crawler.start(Crawler.scala:157) at com.testerhome.appcrawler.AppCrawler$.startCrawl(AppCrawler.scala:342) at com.testerhome.appcrawler.AppCrawler$.parseParams(AppCrawler.scala:310) at com.testerhome.appcrawler.AppCrawler$.main(AppCrawler.scala:90) at com.testerhome.appcrawler.AppCrawler.main(AppCrawler.scala)

101楼 已删除

@zlw_tester 你的 org.xml.sax.SAXParseException 的问题还存在吗?咋解决的?

@seveniruby 思寒,我这边用 2.1.0 的时候也会报上面的错误,尝试很多次都会重复 org.xml.sax.SAXParseException 这同一个错误,用 1.8.0 的版本是没有问题。 跑的时候没有用 conf 文件,就是最简单的命令

小背影 回复

我跟进下 正在要出问题同学的 log 和堆栈

期待 2.1.0 的到来,我还在学习这个工具的用法中,还特别期待 yaml 的用例(可否在 git 中放一个例子?)

daivd 回复

输入--demo 就会自动生成样例

默默的支持就好

雪怪 回复

亲,你咋搞定的, 我用 testcase 也不行呢,能给下案例不

结合 LeakCanary 和 MLeaksFinder 的使用例子有没有?

yunmenzhe 回复

没,我发现还是失败了,在选择服务器的时候,就已经开始了遍历,只是刚好我希望他选择服务器恰好在第一个位置就继续运行下去了 。 最近工作有变动就没再继续跟这问题😲

@seveniruby 思寒,配置文件.yml 在 iOS 应该怎么配置呢?有例子吗? 我目前遇到的问题:不断重启 App,一直只停留在首页,不会遍历。 我的配置如下: defineUrl: # 一以下是 App 导航栏 Tab 按钮的 xpath

  • "//UIToolbar[1]/UIButton[1]/@label"
  • "//UIToolbar[1]/UIButton[2]/@label"
  • "//UIToolbar[1]/UIButton[3]/@label"
  • "//UIToolbar[1]/UIButton[4]/@label"
  • "//UIToolbar[1]/UIButton[5]/@label"

appWhiteList:

  • ios
  • "xxxxx 应用的名字"

baseUrl:

  • "//UIToolbar[1]/UIButton[1]/@label"
  • "//UIToolbar[1]/UIButton[2]/@label"
  • "//UIToolbar[1]/UIButton[3]/@label"
  • "//UIToolbar[1]/UIButton[4]/@label"
  • "//UIToolbar[1]/UIButton[5]/@label"
雪怪 回复

哦,好吧,我改用 1.7.1 版本的了,老版本的配置文件还能运行起来,新版本的部分等后续研究吧。 换工作不研究这个了?

这个可以做 monkey 的深度遍历吗?感觉思路有点像。

yunmenzhe 回复

换工作耽误了几个月 .大会后重新设计新版本.

好东西学习了

等你新版本,新版本出来之前我先把老版本用好了

请问支持游戏遍历会在什么时候发布呢?

guoxd 回复

getpagesource 返回了空内容 你得查查了 我遇到过 一种可能是 appium 的 bug 特定页面处理不当返回内容为空

119楼 已删除

去 github 上看看对应的代码行吧

你好,testcase 对应的是用例吗?配置文件里面可以配置多个 testcase 节点吗?

122楼 已删除
123楼 已删除

@seveniruby 思寒,现在是不是还不支持长按操作,我看源码里面写着 undo,啥时会实现呢

greenplum 回复

已经支持了 2.1.0

@seveniruby 为啥下面的操作执行时成为 click 操作了

testcase:
  name: login
  steps:
  - when:
      xpath: //*[@resource-id='xxx/et_phone']
      action: 10086
    then: []

@seveniruby 我在配置文件里,加入了启动的参数 startupActions,如下 startupActions:

  • swipe("left")
  • swipe("left")
  • swipe("left")
  • println(driver) 但启动到欢迎界面的时候并没有滑动,而是等待段时间就自动退出了 app,看日志是执行了 testcase,请问目前的新版本是用 testcase 参数代替了 startupActions 吗?

@seveniruby 你好,看你的帮助文档是支持 swipe("left") 的,但是执行的时候却报 yaml 语法错误,这是什么问题呢

不好意思是,我 Yaml 写错了。。😀

使用过程中 50% 的情况下会出现如下错误, 看到之前有人提过这样的问题,想再次问下,有没有什么好的解决方案?感谢。 Message: 文件提前结束。 Exception: org.xml.sax.SAXParseException com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(Unknown Source) com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(Unknown Source) javax.xml.parsers.DocumentBuilder.parse(Unknown Source) com.testerhome.appcrawler.RichData$.toDocument(RichData.scala:26) com.testerhome.appcrawler.TemplateTestCase$$anonfun$addTestCase$1$$anonfun$apply$3.apply(TemplateTestCase.scala:64) org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85) org.scalatest.OutcomeOf$.outcomeOf(OutcomeOf.scala:104) org.scalatest.Transformer.apply(Transformer.scala:22) org.scalatest.Transformer.apply(Transformer.scala:20) org.scalatest.FunSuiteLike$$anon$1.apply(FunSuiteLike.scala:186) org.scalatest.TestSuite$class.withFixture(TestSuite.scala:196) org.scalatest.FunSuite.withFixture(FunSuite.scala:1560) org.scalatest.FunSuiteLike$class.invokeWithFixture$1(FunSuiteLike.scala:183) org.scalatest.FunSuiteLike$$anonfun$runTest$1.apply(FunSuiteLike.scala:196) org.scalatest.FunSuiteLike$$anonfun$runTest$1.apply(FunSuiteLike.scala:196) org.scalatest.SuperEngine.runTestImpl(Engine.scala:289)

终结者 回复

@seveniruby 你好,刚看到有时是应用崩溃了返回了上面的错误,看了下说是会自动生成崩溃的日志,找了好久也没看到啊

配置文件实在太强大了,能不能提供一份完整的配置文件附加使用说明 书? 经过调试后我发现几乎所有的报错都能通过黑白名单(Blacklist,urlblacklist)+ 触发条件(triggerActions)这些配置项给绕过去。期待详细配置说明文档。

guoxd 回复

看对应的代码文件吧. 最近的确很忙. 没时间完善文档了.

因为在拼接字符串的时候,有可能包含中文,utf8 中文占 3 个字节,如果文件名过长,导致系统报错(各大系统默认文件名长度是 255)File name too long,appcrawler 在创建文件的时候失败,抛出空指针程序无法继续。

guoxd 回复

2.1.0 也是这样吗, 我记得我修改过,没改的花我就更新下。

我用的是 2.1.0 版本,应该是没更新的;我自己下的源码,编译一份改过的,就没问题了。

安卓和 iOS 用命令行,已经都运行成功了,感谢思寒😃 @seveniruby 另外有个问题是 iOS 的 yaml 配置文件格式是什么?

capability:
    automationName: "XCUITest"
    XXXX

这种配置还是有问题 看源代码解决问题了 iosCapability。。忽略刚才的问题

运行的时候,老是报这个错,该怎么解决啊?

工具很强大。另外,请问一下,我设置了判断 App 崩溃的断言,运行过程中 app 崩了但是报告显示全通过是什么原因?

hulk 回复

原理就是拿 xml 和 xpath 进行断言了。你可以查查当时的 xml。我没数据不好排查。

@seveniruby 程序按 testcase 执行,执行完 testcase 后如何继续执行 monkey 遍历? - action:monkey 对吗?求指导

- when: 
    xpath: //XCUIElementTypeOther/XCUIElementTypeOther/XCUIElementTypeTable/XCUIElementTypeCell
    action: driver.swipe(0.8, 0.8, 0.2, 0.2)
    then: 
      - action: monkey

各位你们好,我用了下遍历工具报了一个错,不知道什么原因,还请指教下。 第一次用,执行命令就是 appcrawler -a xx.apk

plateau 回复

error: Failed to start an Appium session, err was: Error: Command failed: C:\windows\system32\cmd.exe /s /c "C:\gaoyuan\work\sdk\platform-tools\adb.exe -s 978f0bd1 shell "ps 'uiautomator'""

info: [debug] Error: Command failed: C:\windows\system32\cmd.exe /s /c "C:\gaoyuan\work\sdk\platform-tools\adb.exe -s 978f0bd1 shell "ps 'uiautomator'""

at ChildProcess.exithandler (child_process.js:751:12) at ChildProcess.emit (events.js:110:17) at maybeClose (child_process.js:1016:16) at Process.ChildProcess._handle.onexit (child_process.js:1088:5) info: [debug] Responding to client with error: {"status":33,"value":{"message":"A new session could not be created. (Original error: Command failed: C:\windows\system32\cmd.exe /s /c \"C:\gaoyuan\work\sdk\platform-tools\adb.exe -s 978f0bd1 shell \"ps 'uiautomator'\"\"\n)","killed":false,"code":1,"signal":null,"cmd":"C:\windows\system32\cmd.exe /s /c \"C:\gaoyuan\work\sdk\platform-tools\adb.exe -s 978f0bd1 shell \"ps 'uiautomator'\"\"","origValue":"Command failed: C:\windows\system32\cmd.exe /s /c \"C:\gaoyuan\work\sdk\platform-tools\adb.exe -s 978f0bd1 shell \"ps 'uiautomator'\"\"\n"},"sessionId":null} info: <-- POST /wd/hub/session 500 33082.162 ms - 586

error: Failed to start an Appium session, err was: Error: Command failed: C:\gao yuan\sdk\platform-tools\adb.exe -s 978f0bd1 install "C:\Program Files (x86)\Appi um\node_modules\appium\build\unicode_ime_apk\UnicodeIME-debug.apk" Failed to install C:\Program Files (x86)\Appium\node_modules\appium\build\unicod e_ime_apk\UnicodeIME-debug.apk: Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE: Pac kage io.appium.android.ime signatures do not match the previously installed vers ion; ignoring!] 这个问题有人遇到吗?求教

plateau 回复

之前安装了签名不同的输入法吧

确实用 appium 的时候有装一个输入法,但是应用中没有找到此程序的卸载

我换了一个手机试了下,不报之前的输入法的错了,报个一个其他错: error: Failed to start an Appium session, err was: Error: Permission to start ac tivity denied.

plateau 回复

你的 Activity 不对。不是每个 Activity 都有启动权限的,你得找入口 Activity

@seveniruby 感谢你的工具!请教个问题,当某个界面上,uiautomator 获取 dump 文件遇到问题时,appium 会遇到 500 error,此时 appcrawler 会出 exception。 想问一下此时如果想直接 fail 该动作,然后自动 back,再继续,如果要达到这样的效果,我需要怎么配置?

appium exception log:

debug] [MJSONWP] Responding to client with driver.getWindowSize() result: {"width":480,"height":854}
[HTTP] <-- GET /wd/hub/session/a66cad36-4901-4154-adba-cf2499cc194d/window/current/size 200 13 ms - 98
[HTTP] --> GET /wd/hub/session/a66cad36-4901-4154-adba-cf2499cc194d/source {}
[debug] [MJSONWP] Calling AppiumDriver.getPageSource() with args: ["a66cad36-4901-4154-adba-cf2499cc194d"]
[debug] [AndroidBootstrap] Sending command to android: {"cmd":"action","action":"source","params":{}}
[AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got data from client: {"cmd":"action","action":"source","params":{}}
[AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got command of type ACTION
[AndroidBootstrap] [BOOTSTRAP LOG] [debug] Got command action: source
[AndroidBootstrap] [BOOTSTRAP LOG] [debug] Command returned error:java.lang.RuntimeException: Failed to Dump Window Hierarchy
[debug] [AndroidBootstrap] Received command result from bootstrap
[HTTP] <-- GET /wd/hub/session/a66cad36-4901-4154-adba-cf2499cc194d/source 500 204 ms - 154
[AndroidBootstrap] [BOOTSTRAP LOG] [debug] Returning result: {"value":"Failed to Dump Window Hierarchy","status":13}

appcrawler exception log:

2017-09-20 14:26:03 ERROR [AppiumClient.asyncTask.150] exception
2017-09-20 14:26:03 ERROR [AppiumClient.asyncTask.151] org.openqa.selenium.WebDriverException: An unknown server-side error occurred while processing the command. (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 91 milliseconds
Build info: version: 'unknown', revision: 'unknown', time: 'unknown'
System info: host: 'sh-jikun.zenmen.corp', ip: '10.241.53.72', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.12.6', java.version: '1.8.0_131'
Driver info: io.appium.java_client.android.AndroidDriver
Capabilities [{appPackage=com.halo.wifikey.wifilocating, reuse=3, noReset=true, dontStopAppOnReset=true, deviceName=8b26684b, platform=LINUX, deviceUDID=8b26684b, androidInstallTimeout=180000, desired={app=, appPackage=com.halo.wifikey.wifilocating, reuse=3, appium=http://10.241.19.57:4821/wd/hub, noReset=true, dontStopAppOnReset=true, deviceName=10.241.19.57:4821, launchTimeout=120000, appActivity=com.lantern.launcher.ui.MainActivity, androidInstallTimeout=180000, newCommandTimeout=120, autoLaunch=true, platformVersion=, automationName=Appium, autoWebview=false, platformName=Android, udid=8b26684b}, newCommandTimeout=120, platformVersion=4.4.4, webStorageEnabled=false, automationName=Appium, takesScreenshot=true, javascriptEnabled=true, autoWebview=false, platformName=Android, udid=8b26684b, deviceManufacturer=OPPO, app=, deviceScreenSize=480x854, networkConnectionEnabled=true, appium=http://10.241.19.57:4821/wd/hub, warnings={}, databaseEnabled=false, launchTimeout=120000, appActivity=com.lantern.launcher.ui.MainActivity, autoLaunch=true, locationContextEnabled=false, deviceModel=A31c}]
Session ID: a66cad36-4901-4154-adba-cf2499cc194d
2017-09-20 14:26:03 ERROR [AppiumClient.asyncTask.152] java.util.concurrent.FutureTask.report(FutureTask.java:122)
java.util.concurrent.FutureTask.get(FutureTask.java:206)
com.testerhome.appcrawler.driver.WebDriver$$anonfun$2.apply(WebDriver.scala:135)
scala.util.Try$.apply(Try.scala:192)
com.testerhome.appcrawler.driver.WebDriver$class.asyncTask(WebDriver.scala:126)
com.testerhome.appcrawler.driver.AppiumClient.asyncTask(AppiumClient.scala:24)
com.testerhome.appcrawler.driver.AppiumClient$$anonfun$getPageSource$1.apply$mcVI$sp(AppiumClient.scala:302)
scala.collection.immutable.Range.foreach$mVc$sp(Range.scala:166)
com.testerhome.appcrawler.driver.AppiumClient.getPageSource(AppiumClient.scala:301)
com.testerhome.appcrawler.Crawler.refreshPage(Crawler.scala:538)
com.testerhome.appcrawler.Crawler.start(Crawler.scala:140)
com.testerhome.appcrawler.AppCrawler$.startCrawl(AppCrawler.scala:342)
com.testerhome.appcrawler.AppCrawler$.parseParams(AppCrawler.scala:310)
com.testerhome.appcrawler.AppCrawler$.main(AppCrawler.scala:90)
com.testerhome.appcrawler.AppCrawler.main(AppCrawler.scala)
Exception in thread "main" java.lang.NullPointerException
    at scala.collection.immutable.StringOps$.length$extension(StringOps.scala:48)
    at scala.collection.immutable.StringOps.length(StringOps.scala:48)
    at scala.collection.IndexedSeqOptimized$class.isEmpty(IndexedSeqOptimized.scala:27)
    at scala.collection.immutable.StringOps.isEmpty(StringOps.scala:30)
    at scala.collection.TraversableOnce$class.nonEmpty(TraversableOnce.scala:109)
    at scala.collection.immutable.StringOps.nonEmpty(StringOps.scala:30)
    at com.testerhome.appcrawler.Crawler.refreshPage(Crawler.scala:541)
    at com.testerhome.appcrawler.Crawler.start(Crawler.scala:140)
    at com.testerhome.appcrawler.AppCrawler$.startCrawl(AppCrawler.scala:342)
    at com.testerhome.appcrawler.AppCrawler$.parseParams(AppCrawler.scala:310)
    at com.testerhome.appcrawler.AppCrawler$.main(AppCrawler.scala:90)
    at com.testerhome.appcrawler.AppCrawler.main(AppCrawler.scala)

手动使用 uiautomatorview 获取问题页面遇到如下异常,其它页面正常 Error while parsing UI hierarchy XML file: Invalid ui automator hierarchy file.

@seveniruby 思寒老师,这个配置提示有些看不懂了,麻烦请教一下

哪里有配置文件的详细说明?

2017-10-17 12:33:47 INFO [Runtimes$.eval.65] driver.swipe(0.9, 0,5, 0.1, 0.5)
<console>:12: error: overloaded method value swipe with alternatives:
  (startX: Double,endX: Double,startY: Double,endY: Double)Option[_] <and>
  (direction: String)Unit
 cannot be applied to (Double, Int, Int, Double, Double)
       driver.swipe(0.9, 0,5, 0.1, 0.5)
              ^

api 报错

152楼 已删除

@seveniruby 支持 macaca 的哪个版本呢?

dengwei729 回复

2.1.1 版本刚做了 appium 的 1.7.1 的适配,Macaca 的最新版本还没做

有游戏 APP 遍历?想了解下,是类似 Gautomator 这种类型 还是只是 monkey 的呀?

这个厉害了!

win7 下 appium 进程会无响应,JAVA 吃的内存会越来越多,有什么办法吗

jojotester 回复

新版本已经优化了, 还没正式发布,还在内部试用中。

跑的 Android apk,在输入的时候提示这个 2017-12-28 00:02:04 ERROR [AppiumClient.asyncTask.153] exception 2017-12-28 00:02:04 ERROR [AppiumClient.asyncTask.154] org.openqa.selenium.WebDriverException: An unknown server-side error occurred while processing the command. Original error: java.lang.NullPointerException at android.support.test.uiautomator.UiObject2.setText(UiObject2.java:601) at io.appium.uiautomator2.model.UiObject2Element.setText(UiObject2Element.java:129) at io.appium.uiautomator2.handler.SendKeysToElement.safeHandle(SendKeysToElement.java:83) at io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:56) at io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:202) at io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:193) at io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:44) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345) at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:102) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345) at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:435) at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293) at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267) at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:250) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:345) at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1294) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366) at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:352) at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:911) at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131) at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:611) at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:514) at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:468) at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:438) at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:140) at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144) at java.lang.Thread.run(Thread.java:841) (WARNING: The server did not provide any stacktrace information) Command duration or timeout: 0 milliseconds

思寒,appcrawler 目前的 2.1.0 版本,支持新老版本的界面对比 (Doing) 还没有开放吗

https://github.com/Eaway/AppCrawler 这个也是本文作者写的吗

@jojotester 你好 请问你 File "C:\Users\jxiong\AppData\Local\Programs\Python\Python36\lib\configparser.py", line 1012, in _read for lineno, line in enumerate(fp, start=1):这个问题怎么改的啊?看到你 16 年解决过

土豆 回复

问题解决了吗 ,我也遇到这个问题了

你好,一些依赖的 jar 包下不到,怎么解决?谢谢

165楼 已删除

获取 iOS 的界面经常超时啊 😢

@seveniruby 这个什么用?

导入 build.sbt 工程时,报错如下图,这是什么原因。

仅楼主可见

请问下,我测试的 app 显示 APP 主界面时会再 show 一个全屏的类广告页面, 脚本在这个时候就会判断为不在 app 中并执行 backapp 操作(看 appcrawler 执行日志前后有 “set action to backApp”) 导致直接回退到手机主页面再一次测试,这个情况能怎么调整吗?

FuhuiLiu 回复

加个等待,或者 trigger action,发现是广告页或者划屏页就自动等待或者滑动。

情况搞明白了,应该是 APP 第一次开启时会弹权限申请,此时 crawler 会认为系统框架是 app, 当操作点击过了系统这种弹框后真正进入 APP 时会因为比对 activity 栈, 导致认为不在 APP 页面而执行 backapp 操作

结合当时输出日志情况,猜测是这样的,这种加等待也没用 ps:不过等待是怎么个写法,给的 xueqiu_private.yml 里面似乎没找到类似的功能代码

哦对,现在的方案安装完 app,手动把所有权限加上来避过这个问题, 不知道有没有更好的替换方案?

FuhuiLiu 回复

有个 app 白名单 appWhiteList,加进去就好了

了解,我在 git 上的 xueqiu_private.yml 配置中没找到类似的示例, appcrawler 有完整的 api 说明文档吗

怎样配置文件里是现上滑刷新,哪位用过指点下

怎样在配置文件里实现滑动刷新,哪位用过指点下,

defineUrl 和 baseUrl 怎么用能讲下吗

求助思寒,本地操作运行 yml 文件时,报错 Exception in thread "main" java.util.NoSuchElementException: last of empty ListBuffer,怎么解决呢?

思寒老师,请问运行的时候报错,麻烦帮忙看一下 Exception in thread "main" java.util.NoSuchElementException: last of empty ListBuffer at scala.collection.mutable.ListBuffer.last(ListBuffer.scala:401) at com.testerhome.appcrawler.DataRecord.last(DataRecord.scala:40) at com.testerhome.appcrawler.Crawler.doElementAction(Crawler.scala:985) at com.testerhome.appcrawler.Crawler.runStartupScript(Crawler.scala:238) at com.testerhome.appcrawler.Crawler.start(Crawler.scala:152) at com.testerhome.appcrawler.AppCrawler$.startCrawl(AppCrawler.scala:344) at com.testerhome.appcrawler.AppCrawler$.parseParams(AppCrawler.scala:312) at com.testerhome.appcrawler.AppCrawler$.main(AppCrawler.scala:92) at com.testerhome.appcrawler.AppCrawler.main(AppCrawler.scala)

你好,请问点击登录之后等待页面跳转时报错:需要位置路径, 但遇到以下标记 “true”,这个是什么情况呀

关闭登录页面后跳到首页,然后就一直点击 “back” 按键,在首页 toast 提示:“再按一次退出”。首页其实没有 back 按钮或返回键。是 pagesource 没有获取到么,我看 dom 上其实已经拿到了。看样子是 node size 找不到为 0

liluliu 回复

这个我也遇到过,后来下载 2.4.0 的版本包就可以。

哪位大佬帮忙解决一下

2.4.0 版本使用 diff 功能报错,哪位帮忙看下 Exception in thread "main" java.lang.ExceptionInInitializerError at com.testerhome.appcrawler.AppCrawler$.parseParams(AppCrawler.scala:26 6) at com.testerhome.appcrawler.AppCrawler$.main(AppCrawler.scala:91) at com.testerhome.appcrawler.AppCrawler.main(AppCrawler.scala) Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of com.testerhome.appcrawler.URIElement (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- o r property-based Creator) at com.fasterxml.jackson.mod ule.scala.deser.MapBuilderWrapper["XXXXX-MainActivity.ta g=start.id=start"]->com.testerhome.appcrawler.ElementInfo["element"]" title="">Source: (StringReader); line: 15, column: 7

6dingdong6 回复

请问你这最后是怎么解决的,我用的是 2.4.0 版本也还是有这个问题

小肉包 回复

没有解决,我换了一个遍历工具😂

6dingdong6 回复

你换的什么工具。。。。。。

清风上灬 回复

最后换了 maxim,但是这个工具不支持 ios,只能暂时先放弃 ios 了

6dingdong6 回复

这个全称是什么 有链接么

为什么我运行了命令,成功打开 app 了,但一直停留在 app 首页,什么都没点的?

java 版本的算我一个

 xml format
Exception in thread "main" java.lang.NoSuchMethodError: 'void com.sun.org.apache.xml.internal.serialize.OutputFormat.<init>(org.w3c.dom.Document)'

appcrawler2.4.0 + java 14 报错。 难道只能用 java 8?java -jar appcrawler-2.4.0-jar-with-dependencies.jar -c demo.yml -vv 运行后报错, 有大佬可以解答下吗?

请问,怎样才能参与 AppCrawler2.6.0 内测?

思寒,想获取 AppCrawler2.6.0 内测版本,望回复哦😺

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册