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

测试覆盖着整个软件开发的生命周期。从需求评审开始,测试工程师就要介入了解需求,并编写用例;开发过程中,研发工程师们会针对测试用例,编写单元测试;开发完毕后,测试工程师介入进行集成测试;上线后还需要进行线上跟测,追踪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

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

image

由于上文中说过,这种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

  1. 执行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

  1. 从生成的Monkey Log中查看是否有Android的异常

为了使测试过程能够多样化,随机模拟更多的场景,一般情况下,需要运行第5步多次,并且每次都修改一下-s(seed)的值,以产生足够多的随机测试样本。关于Monkey的各种参数的用法,官网上有很详细的说明:

https://developer.android.com/studio/test/monkey.html

另外网上也有不少成熟的介绍,这里就不再赘述。

场景2: iOS Monkey

iOS的Monkey测试其实是利用了iOS官方提供的UIAutomation工具,这个工具还是比较强大的,可以允许开发者使用JS脚本来定义整个测试过程,并且可以精确操作界面上的每个元素,如果和Instruments结合起来使用的时候,还支持操作过程录制和回访的功能(虽然比较鸡肋)。针对Monkey测试,Github有个牛人写了一套测试脚本,能干的事和Android的Monkey一样,并且通用性很强:

https://github.com/jonathanpenn/ui-auto-monkey

于是我们结合这个工具和JS脚本看看在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
  2. instruments_ui_automation
    用于封装UIAutomation的Instruments命令,同样将需要的参数暴露出来,完整的Action见这个链接,可以根据需要自行修改: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

自定义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的一些高级用法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,874评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,151评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,270评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,137评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,116评论 5 370
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,935评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,261评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,895评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,342评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,854评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,978评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,609评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,181评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,182评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,402评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,376评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,677评论 2 344

推荐阅读更多精彩内容