低代码到底是不是行业毒瘤?一线大厂怎么做的?戳此了解>>> 了解详情
写点什么

Fastlane 实战(四):自动化测试篇

2016 年 12 月 11 日

测试覆盖着整个软件开发的生命周期。从需求评审开始,测试工程师就要介入了解需求,并编写用例;开发过程中,研发工程师们会针对测试用例,编写单元测试;开发完毕后,测试工程师介入进行集成测试;上线后还需要进行线上跟测,追踪 Bug。所以可以看出,测试对于软件的重要性不言而喻,毕竟可靠的质量才是产品的基本竞争力。

很多时候,测试工程师不仅要测试新增的功能和有变更的功能,还需要花大量时间对核心功能进行测试覆盖,以及对老版本进行兼容性测试。而这些工作对于移动客户端来说是无法避免的,因为无论架构设计如何解耦,都不能完全保证改动的范围约束在当前的模块;另外,也不可能指望新版本发布后,所有人都在第一时间升级。

自动化测试

为了简化测试,很多针对移动客户端的自动化测试工具诞生,比如 iOS 和 Android 官方提供的 Monkey Runner,UIAutomation;开源社区贡献的 Appium,Macaca 等等。

其实从分层的角度来说,对于移动客户端来说,自动化测试大概可以分为如下两个部分:

  1. API 自动化测试:保证接口的格式正确,字段类型无误。
  2. UI 自动化测试:模拟用户在手机上的操作行为,断言结果。

对于 API 来说,可测试性较高,耦合性较小,所以自动化测试工作比较容易开展。对于 UI 来说,自动化测试的投入产出比就非常的大了,首先对于界面上是否展示正确的元素而编写测试代码,本来就是一件比较困难的事;另外,一旦界面做了改动,相关的测试代码就需要重写,尤其是创业公司的产品,迭代速度很快,界面上的调整又很频繁,过多的 UI 自动化测试反而会带来更大的维护成本。所以目前来看,UI 自动化测试能够覆盖 10% 左右的核心稳定模块就算是一个较为合适的选择了,当然这个也需要视公司的产品规划和迭代流程而定。

UI 自动化测试

UI 自动化测试有个比较著名的开源工具叫做 Appium ,同时支持 iOS 和 Android 平台,基于 Server 和 Client 模式,支持多种语言编写测试逻辑,应该是目前最为流行的测试工具之一。对于这个工具 Fastlane 有个对应的 Action:Appium,这个 Action 可以帮助大家将 Appium 集成到 Fastlane 的自动化流程中,具体用法可以在命令行中查看,输入:

fastlane action appium然后,命令行中会打印出具体的参数和用法:

(点击放大图像)

由于上文中说过,这种UI 自动化测试的形式性价比比较低,在UI 不断变化的情况下,测试复杂度和维护成本都比较高,所以这里就不再展开讨论,有兴趣的同学可以自己尝试。

Monkey 测试

自动化测试还有一个比较经济实惠的方式,即 Monkey 测试,这个其实很形象,就像猴子在屏幕上乱点一样,虽然所有的行为都是随机的(包括:点击,触摸,滑动,双击,手势等等),并且没有目的性,但是对于一些基础性的测试,如:安装,卸载,内存占用,电量,设备兼容和一些比较明显的错误引起的崩溃,是一个很合适的方式。

我们团队使用 Monkey 测试大约 2 个月的时间,值得高兴的是,使用 Monkey 后,我们可以更加全面的覆盖到 APP 的从安装到卸载的生命周期,另外还对于 APP 的内存,电量,网络的使用情况有了更深的认识,并且确实帮助我们提前发现了几处容易引发崩溃的地方。

Android 和 iOS 平台本身都提供了 Monkey 测试工具,Android 的就叫 Monkey,官方 adb monkey 工具中已经内置了很多运行参数,所以只需要简单配置一下即可使用。

场景 1:Android Monkey

下面我们看看 Android 一般运行 Monkey 测试的步骤:

  1. Git Pull 拉最新的代码
  2. 执行./gradlew clean 命令清理环境
  3. 执行./gradlew assembleTest 打包测试版本
  4. 执行命令安装最新的测试版本: adb shell monkey -p com.wanmeizhensuo.zhensuo -c android.intent.category.LAUNCHER 1
  5. 执行 Monkey 测试命令: ```

adb shell monkey -p com.wanmeizhensuo.zhensuo
–ignore-security-exceptions --ignore-crashes --ignore-timeouts
–monitor-native-crashes --throttle 300 --pct-touch
94 --pct-motion 6 -s 1000 -v -v -v 6000

复制代码
6. 从生成的 Monkey Log 中查看是否有 Android 的异常
### 场景 2: iOS Monkey
1. Git Pull 拉最新的代码
2. Cocoapods 更新依赖库
3. 打包并安装最新的 ipa 到设备上
4. 使用 instruments 提供的命令行工具执行 JS 脚本(或者打开 Instruments 工具,将 JS 代码拷贝到输入框中,然后运行):
5. 从生成的 Crash Log 中查看是否有崩溃。如果使用模拟器的话,那么这些 Crash 文件会输出到 /Library/Logs/DiagnosticReports 下面
注:Instruments 完整命令如下:

instruments
-t /Applications/Xcode.app/Contents/Applications/Instruments.app/
Contents/PlugIns/AutomationInstrument.xrplugin/Contents/
Resources/Automation.tracetemplate #Automation 模板路径
-w 68430CE4-8FC9-41EA-A9E3-5D3127BC9086
/Users/Thierry/Library/Developer/Xcode/DerivedData/Gengmei-
fwlefrcslagvocbtnylgubtdgofr/Build/Products/Debug-iphonesimulator/
Gengmei.app #设备 UDID 和安装包路径
-e UIASCRIPT /Users/Thierry/.Jaguar/script/monkey/monkey.js #JS 脚本路径
-e UIARESULTSPATH /Users/Thierry/.Jaguar/log/testin #输出结果文件夹

复制代码
### 使用 Fastlane 自动化 Monkey 测试
讲到这里,大家应该可以看出,以上两个场景每次重复这些步骤其实很耗费时间的,所以我们完全可以将这些步骤整理出来,然后交给 Fastlane 去管理,这样既简单又方便以后的维护。
在开始编写具体的 Lane 之前,我们首先新建几个自定义的 Action:
1. **android\_monkey**
用于封装 Android Monkey adb 命令,然后将需要的参数暴露出来,完整的 Action 见这个链接,可以根据需要自行修改: [https://github.com/GengmeiRD/Fastfiles/blob/master/fastlane/actions/android\_monkey.rb](https://github.com/GengmeiRD/Fastfiles/blob/master/fastlane/actions/android_monkey.rb)
2. **instruments\_ui\_automation**
用于封装 UIAutomation 的 Instruments 命令,同样将需要的参数暴露出来,完整的 Action 见这个链接,可以根据需要自行修改:[https://github.com/GengmeiRD/Fastfiles/blob/master/fastlane/actions/instruments\_ui\_automation.rb](https://github.com/GengmeiRD/Fastfiles/blob/master/fastlane/actions/instruments_ui_automation.rb)
3. **install\_app\_on\_simulator**
如果你用 iOS 模拟器测试的话,需要借助 ios-sim 这个工具来将 app 文件安装到模拟器上,所以这个 action 就是用来封装 ios-sim 命令的,链接如下:[https://github.com/GengmeiRD/Fastfiles/blob/master/fastlane/actions/install\_app\_on\_simulator.rb](https://github.com/GengmeiRD/Fastfiles/blob/master/fastlane/actions/install_app_on_simulator.rb)
自定义 Action 写完后,接下来我们来编写具体的 Lane。
针对 ** 场景 1:Android Monkey**

desc “Android monkey test”
lane :do_monkey_test do |options|
times = options[:times] || 2
project = options[:project]
apk_path = options[:apk_path]
package_name = options[:package_name]

复制代码
hipchat(message: "Start monkey test on #{project}")
git_pull
gradle(task: "clean")
gradle(task: "assembleGmtest")
(1..times.to_i).each do |i|
adb(command: "install -r #{apk_path}")
adb(command: "shell monkey -p #{package_name} -c android.intent.category.LAUNCHER 1")
# 等待 30 秒,确保闪屏页被 Finish 后,进入到主页.
sleep(30)
android_monkey(package_name: "#{package_name}", count: '1000', seed: "#{10+i}")
end
hipchat(message: "Execute monkey test on project #{project} successfully")

end

复制代码
每次执行如下命令即可完成 Android Monkey 测试:
`fastlane do_monkey_test times:3 project:GengmeiAndroid apk_path:./GengmeiAndroid_test.apk ...`针对 ** 场景 2:iOS Monkey**,Lane 如下:

desc “UI automation test”
lane :do_monkey_test do |options|
times = options[:times] || 2
scheme = options[:scheme]
project = options[:project]
device_udid = options[:device_udid]
device_type = options[:device_type]
script = options[:script]
report_output_path = options[:report_output_path]

复制代码
hipchat(message: "Start monkey test on #{project}")
git_pull
cocoapods
xcodebuild(scheme: scheme, arch: 'x86_64', sdk: 'iphonesimulator9.3',

workspace: “#{project}.xcworkspace”, configuration: ‘Debug’)
app_path = get_debug_app_path(scheme: scheme, project: project)
(1…times.to_i).each do |i|
install_app_on_simulator(device_type: device_type, app_path: app_path)

使用 ios-sim 命令安装 app 到模拟器,如果是真机的话,则使用 ios-deploy

复制代码
sleep(30)
instruments_ui_automation(device: device_udid, app_path: app_path,

report_output_path: report_output_path, script:script)
end

复制代码
hipchat(message: "Execute monkey test on #{project} successfully")

end

复制代码
每次执行如下命令即可完成 iOS Monkey 测试:
`fastlane do_monkey_test times:3 scheme:Gengmei-Test project:GengmeiiOS device_udid...`最后在完成 Monkey 测试之后,我们还需要对产生的测试日志进行过滤,分析,并形成报表,然后发送邮件给相关同学。如果更进一步的话,当分析到日志中有异常或崩溃的情况,我们还可以编写程序,向类似 Jira 的项目管理工具中自动提交一个 Bug,这样可以形成一个完整的 Monkey 自动化测试流程(Monkey 测试 -> 异常收集 -> 异常分析 -> 异常提交 -> 异常处理)。
## 结语
关于 Monkey 测试在 iOS 和 Android 平台上的使用工作,其实我们开展的时间并不算长,如何能够更加合理和有效的利用 Monkey 测试,还需要我们花一些时间来思考,实践和完善,不过庆幸的是,一开始我们就借助了 Fastlane 这个强大的工具来处理整个流程,让整个过程变得既简单又高效。如果大家有更好的使用场景和案例,也欢迎讨论和分享。
下一篇文章是整个 Fastlane 系列的收尾篇,在这篇文章中我将结合一些实际使用的场景和案例,着重介绍一下 Fastlane 的一些高级用法。
- - - - - -
感谢 [徐川](http://www.infoq.com/cn/author/%E5%BE%90%E5%B7%9D) 对本文的审校。
给 InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 [editors@cn.infoq.com](mailto:editors@cn.infoq.com)。也欢迎大家通过新浪微博([@InfoQ](http://www.weibo.com/infoqchina),[@丁晓昀](http://weibo.com/u/1451714913)),微信(微信号:[InfoQChina](http://www.geekbang.org/ivtw))关注我们。
2016 年 12 月 11 日 16:593458

评论

发布
暂无评论
发现更多内容

在你所在的公司(行业、领域),正在用大数据处理哪些业务?可以用大数据实现哪些价值?

跳蚤

登陆用户身份获取

程序员架构进阶

架构设计 认证授权 28天写作 3月日更

11|PPT教程|结束页的设计和制作

青城

与前端训练营的日子 -- Week20

SamGo

学习笔记

mybatis 添加日志功能

xiezhr

mybatis 日志

《Redis 核心技术与实战》学习笔记 06

escray

redis 学习笔记 28天写作 3月日更 Redis 核心技术与实战

寻找被遗忘的勇气(二十一)

Changing Lin

3月日更

热烈祝贺中国广告协会户外广告分会第五次会员代表大会顺利召开

󠀛Ferry

七日更 3月日更

实操 | 剖析 Java16 新语法特性

高翔龙

Java 架构 java16

写代码的这群人不写文档,为什么 (上篇)

御剑

程序员 架构

MongoDB中的正则表达式

Kylin

mongodb 3月日更 21天挑战

线上问题的一点反思

风翱

复盘 3月日更 线上问题

第11周课后练习-安全稳定

潘涛

架构师训练营 4 期

uni-app跨端开发H5、小程序、IOS、Android(五):uni-app数据绑定

黑马腾云

html5 微信小程序 uni-app iOS Developer 3月日更

数据库设计

在即

28天写作 28天挑战 3月日更

Wireshark数据包分析学习笔记Day18

穿过生命散发芬芳

Wireshark 数据包分析 3月日更

树集合总结

我是程序员小贱

3月日更

翻译:《实用的Python编程》07_02_Anonymous_function

codists

Python

Ubuntu 日常使用问题及解决

依旧廖凯

28天挑战 3月日更

福利来袭!耗资55亿真实落地的网约车项目白皮书、部分源码/视频教程、开发手册限时开源!

程序员小毕

Java 架构 面试 分布式 网约车

主流分布式文件系统总结

跳蚤

思呓(2)

型火🔥

学习 架构 分布式 解耦

ES6中的新特性:Iterables和iterators

程序那些事

nodejs ES6 程序那些事

Python中熟悉又陌生的string库

IT蜗壳-Tango

3月日更

开源与商业产品

ES_her0

3月日更

Gradle无法访问Nexus私服仓库-offline

wjchenge

How to Connect 2 Cisco Switches Together

心在飞

爱了!阿里高工纯手打金三银四Java架构面试大全,涵盖近年来1000余道大厂面试真题,差距不止一点点!

Java王路飞

Java 程序员 架构 面试 分布式

javax.imageio.IIOException: Unsupported Image Type

wjchenge

产品经理面试常见问题总结2

lenka

3月日更

Flutter开发:给image设置圆角的方法

三掌柜

flutter 3月日更

2021 ThoughtWorks 技术雷达峰会

2021 ThoughtWorks 技术雷达峰会

Fastlane实战(四):自动化测试篇-InfoQ