Appetizer 利用模拟器全自动检测 APP 在全 Android 版本上是否会首屏闪退

AppetizerIO · 2017年05月14日 · 最后由 老马 回复于 2017年09月28日 · 5201 次阅读
本帖已被设为精华帖!

用途:作为最基本的常规测试,全自动,用模拟器,4.4-7.0,开发包/混淆后的包会不会首屏闪退

会提到的小技术:

  1. 怎么全自动检测 APP 安装后首屏启动有没有闪退
  2. 怎么自动管理一堆 4.4-7.0 的模拟器, 然后拿个开发包逐个系统自动安装、启动、授权、甚至简单的交互

为什么做这个

Appetizer 质量监控对 APK 进行 DEX 代码插桩,然后插装包运行时能监控质量(crash, http,卡顿等等),DEX 代码插桩是一个很底层的技术,大家有个疑问,插桩后会不会闪退啊,你们怎么确保这个事情的。我们的流程是这样的:

  1. 我们的质量监控代码托管在 GitHub 上,凡是 commit 到 master(意味发版),触发 webhook 到我们的持续化集成服务器,自动 pull,build
  2. 我们保存了生产中的 APK 文件,会自动用这个新质量监控插件,全部插桩一遍,如果插桩失败(基本没有)会立即发邮件
  3. 我们的持续化集成服务器没有显示器(叫 headless server),会自动启动 4.4-7.0 模拟器 N 台,然后每一个 APK 进行安装、启动、授权,检测有没有首屏闪退
  4. 所有闪退或者其他问题,会自动出报告,搜集 logcat,apk 信息,发邮件,然后才由人工参与,这个全自动过程结果如下: 标题里,2017 年 5.13 做的在 api level 23 的模拟器上的结果,每行是一个 apk,成功的有截图 (png),或者无法安装(not_installed)或者闪退(bad),点击即是 log 我们用这套全自动流程回归,并确保我们的质量,目前 5.0+ 系统上闪退率为 0,这里看到很多无法安装是因为用了 x86 模拟器;4.4 比较挫,在修复;整个流程吃满 12 核 cpu,32G 内存的小服务器,需要 50 分钟左右

全自动管理一堆模拟器

一般大家都用 Android Studio,点击 AVD Manager,额然后。。。 不,我们要全自动化
看一下所有 Android 工具链都是可以命令行执行的,从安装系统镜像,到造一个模拟器配置,到创建 sd 卡,到启动 emulator,因为 Google 内部,也有一套类似我们的全自动模拟器 headless 链。但是!但是!这套命令行特别难用,每次都要看一遍文档,所以我做了个包装,代码我放在这里了:https://github.com/appetizerio/haem

Headless Android Emulator Manager (haem)
Terminology:  只要记住四个概念
target - something like android-19 android-23 目标平台,比如android-19, android-23
abi - x86 x86_64 armeabi-v7a or arm64-v8 ABI,就是x86还是ARM,就这四种选择
avd - an arbitrary name for an Android Virtual Device (AVD)  模拟器配置名
port - every emulator listens on a local port, which can be inferred from its adb serialno, e.g., emulator-5444 模拟器的端口,比如emulator-5444端口对应就是5444
Usage: haem.py [OPTIONS] COMMAND [ARGS]... 好了,很简单,命令,参数和git一样

Options:
  --help  Show this message and exit.

Commands:
  check  确认你的环境能否跑模拟器,没有参数
  create 创建一个模拟器配置 参数 AVD TARGET 见上
  delete 删除一个模拟器配置 参数  AVD
  install 安装一个TARGET
  list 列举现在已经创建的模拟器配置
  running 用adb devices报告现在运行的模拟器
  start 启动模拟器 参数AVD
  stop 停止模拟器 参数PORT

如果对细节感兴趣的,看看这个的代码就知道了,Python 的,都是 stackoverflow 上行之有效的方法(比如好好退出我找了一阵子)

有了这个,一个脚本启动一麻袋模拟器(要记得自己的内存)

怎么全自动检测 APP 安装后首屏启动有没有闪退

这个,有些坑

安装

adb 安装再普通不过了,注意了,>=21(5.0)的时候要动态授权,所以最好在安装时用上-g,代码如下,不翻译了

# d 是设备串号,outpath是apk路径
opts = "-g " if int(apilevel) >= 21 else "" # grant all runtime permissions for api>=21
install_info = subprocess.check_output('adb -s %s install %s%s' % (d, opts, outpath), shell=True)

安装可能失败,找 install_info 里面有没有 Failure

启动

清了 logcat 再启动,这个 Monkey 命令就帮你省了 activity 名(很多人会用 am)

# stage 2.2: clear logcat
subprocess.call('adb -s %s logcat -c' % (d, ), shell=True)
# launch it
subprocess.call("adb -s %s shell monkey -p %s 1" % (d, pkg), shell=True)

启动后 12 秒一般就够了,然后抓回来 logcat,-d打印到屏幕走人

logcat_info = subprocess.check_output('adb -s %s logcat -d' % (d, ), shell=True)

检测有没有闪退

先贴代码

# d是设备串号,pkg是apk的包名
wininfo = subprocess.check_output('adb -s %s shell dumpsys window windows' % (d, ), shell=True)
# stage 2.4: check if the app activity is focused
launched = False
for l in wininfo.splitlines():
    if 'mCurrentFocus' in l and 'Application Error' in l:
        launched = False
        break
    if 'mCurrentFocus' in l or 'mFocusedApp' in l:
        launched = launched or pkg in l

首先 dumpsys window windows这个命令会输出目前系统一层层的窗口层次(比如有 launcher,弹出框什么的),不详细解释了,有兴趣的可以去看一下,比较直观
重点是 mCurrentFocus(当前最上面的那个框)和 mFocusedApp(当前最上面的那个 APP)
有几种可能:

  1. APP 启动了,正常,那么应该顶层就是它这行应该都包含 APP 包名
  2. APP 启动了,闪退了,啥都没,回到桌面了,那么 mCurrentFocus 应该变成了桌面
  3. APP 启动了,碰到个坑,crash 了,弹框说"应用程序已经退出",这是个坑,这时两行还都是 APP 包名,和情况 1 差别是 mCurrentFocus 那行会告诉说有一个弹出框,名字叫 Application Error 因为安装时会授权 runtime permission,所以避免了很多首屏弹框要权限 好了,聪明的你整理一下逻辑就是上面那些了 针对 APP 还可以在启动后稍微自动点几下来到主界面,都是脚本活

后记

  • 人力可能也不复杂,但是有自动化方案的时候,我们团队总是选择花时间做自动化:1. 人做机械的事情会出错 2. 不要和电脑抢活干 3. 电脑很笨人很聪明,人做电脑不能做的事情
  • 质保流程可以长一点,但是自动化一点,一点点累积起来的是质量也是专业
  • 有兴趣可以去看看我们实战里面用插桩(呵呵,广告):https://testerhome.com/topics/8174
  • 这个流程还在持续更新中,haem 也是会增加新功能,意见建议一直在学习
  • 周末深夜分享没有泡面这样好么
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 14 条回复 时间 点赞

这个在测试兼容的时候作为最基本的一个点就已经包括了...如果你要独立出来,从 4.4-7.1 也才 6 个版本.
另外你用模拟器的话,很多类型的 app 在模拟器上都是打不开 (首屏闪退) 的,例如加了百度地图 sdk
的.
我觉得就从考虑 android 版本的角度上意义不是很大...不过那些机型特别多的公司和云测试平台倒是可以采用这个.

思寒_seveniruby 将本帖设为了精华贴 05月15日 11:40
哈喽 回复
  1. 真机少的情况下,模拟器随起随用,全版本覆盖,喝口咖啡的时间就搞定,不用等兼容性报告,开发自己也可以用
  2. 真机可以用来开发调试,插上也能增加兼容性机型,即插即用
  3. 如果公司设备多,用云管理,那么可以固定一组用来测兼容,总而言之模拟器比较灵活(8.0 来了),真机比较真(废话),搭配使用
  4. 是有模拟器打不开的,但是我们遇到的也不是非常多,百度 sdk 我们碰到过几个
  5. 对于机型多或者 APP 多比较有用,何乐而不为

@appetizer.io 用 Genymotion 怎么样?

@snake 比自带好很多,模拟的面也很广,不过好像最近开始全面收费了,除了那个 fun zone 好像可以其他不行,以前我们也用过

模拟器启动比较慢,你们是怎么同时启动 N 个虚拟机的?

王华 回复

我们是 mac/linux,nohup emulator xxxx &,启动就会转后台
内存和 cpu 充足的情况下,一下 4-8 台没问题
windows 下命令行我不是很熟,最简单开多个 cmd 一个个开,如果有 cygwin/msys/github commands 可以就 用上面 linux 的方法

am 里面有个 am monitor 可以监测应用 crash 和 ANR,楼主可以试试。

甬力君 回复

恩,我们 Appetizer 其实就是抓 APP 的 crash 和 ANR,就怕一些 DalvikVM 层次的闪退。多谢分享

请问闪退为什么不直接分析 logcat 日志呢?

xiaqing 回复

这玩意主要是自动化检测多机上是否闪退,如果闪退了进一步分析也是基于 logcat 日志的。上面写了 logcat 日志会被抓回来做进一步分析,我们自己根据我们的业务有一套 grep 脚本,用来分析一个闪退的 apk 大致的原因

AppetizerIO 回复

哦 明白了。先进行闪退判断,如果闪退再分析原因。

@appetizer.io haem 这个命令行工具 只是针对 android sdk 自带的 AVD 模拟器么? 可 AVD 模拟器很耗硬件 而且巨慢。
所以 我想问下 是否也是支持 genymotion 模拟器的,但这个模拟器是半商业化的,也提供了 genymotion-shell 和 GM-Tool 之类的命令行工具,但不知道 haem 也能控制和调用 genymotion 模拟器。
https://docs.genymotion.com/Content/Home.htm

Genymotion-Shell-2.10.0-Guide.pdf
从这个里看 也看到了一些类似的设备启动和控制命令

老马 回复

haem 只是用来方便我启动一群 emulator 的,没几行
genymotion 我也用,现在免费版限制越来越多了,核心部分适配下 genymotion shell 应该就好了
可 fork,也可 pull request :-)

AppetizerIO 回复

呵呵 g 工具 是需要许可 收费的。。。

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