专栏首页一个番茄说移动开发流水线建立以及自动化测试

移动开发流水线建立以及自动化测试

工业时代流水线的发明将生产任务的效率大大提升。同样,在软件开发过程中流水线的建立也能帮助我们更好的产出、提升效率。

流水线的建立准则应该符合每个团队自己的需求,比如你的团队管理策略、分支管理策略,接下来以我们最近的给客户做的案例进行总结说明:

我们首先需要制定我们流水线的策略,需要哪几个任务,进行任务的拆分:

iOS:

| 主分支每次提交进行构建触发单元测试 
|   
|--功能测试构建分发
|   |
|   |--各个执行功能测试的节点并行执行功能测试
|       |
|       |--聚合各个节点的功能测试结果输入报告
|
|--adhoc分发通知测试人员
|
|--enterprise分发通知测试人员
|
|--appstore提审核      
|

Android:

| 主分支每次提交进行构建触发单元测试 
|   
|--功能测试构建分发
|   |
|   |--各个执行功能测试的节点并行执行功能测试
|       |
|       |--聚合各个节点的功能测试结果输入报告
|
|--打release包通知测试人员测试
    |
    |--打各种渠道包

其中的功能测试板块由客户的测试团队负责日常的监控以及维护,不干扰开发团队日常的开发。不是整个任务成功的必要条件,而在我之前的开发项目中,功能测试是由开发人员与测试人员一起结对书写,因此会把它作为发测试包的前置步骤,这点根据每个团队的实际情况考量。

工具集:

工欲善其事,必先利其器。要想自动化整个过程,离不开工具的支持。


通用:

Jenkins:用的最广持续集成工具,但是本身并不提供流水线功能,需要插件支持

Gem:ruby包管理工具,比如我们执行功能测试Appium、Calabash等都是通过gem来安装的。

rbenv:管理ruby,用它来统一ruby环境。

bundle:用来管理gem包,比如gem包的版本等。

rake:用ruby时间的类似于make的构建工具,我们的任务脚本使用rake来写的,选自己顺手的就好了。

cucumber:基于BDD的自动化测试框架

iOS:

shenzhen:对,深圳,作者写了一堆用城市命名的工具。这个是用来构建ipa以及分发的,不过我只用了它的分发功能,还是直接用的xcodebuild构建。

calabash:iOS端用来进行自动化功能测试的工具,基于cucumber。

Android:

Appium:类似于calabash的自动化测试框架。之所以没有在安卓上用calabash,是因为项目中用了蚂蚁金融的一个SDK,其对测试不太友好,不支持像calabash这样使用Instrumentation的框架。


关键设计:

持续对主分支进行构建:

我们需要保证开发团队的每一次代码提交都是能工作,能通过测试的,相比传统开发过程中在最后关头进行测试,大大降低了风险。

如下图,需要在任务配置中写上执行策略,比如你想每两分钟去检测一次你的代码库有没有代码变化,如果有变化,Jenkins会立刻开始执行构建。

每两分钟检测一次代码库

拉取下了代码之后之后需要构建并执行单元测试,iOS使用xcodebuild,安卓使用gradle

如何串连流水线:

当构建没问题之后,我们需要在构建后步骤中将下游的任务串连起来,这里有两种方式,一种是自动触发下游任务,一种是手动触发。比如我们的发包步骤就是运营人员手工操作,执行功能测试到合并报告就是自动进行的。

自动触发: 这里需要选择Trigger parameterized build on other projects,指明下游任务的名字。根据需要制定触发条件,以及传递的参数等。

自动触发截图

手动触发:

这里需要选择Build other projects(manual steps),我们需要指定下游任务的名称。传递git commit过去是为了保证下游任务产品代码与当前保值一致,除此之外还会传递一些预定义的参数到下游。

手工触发截图

并行执行功能测试

需求是需要在多台节点上并行地执行功能测试,比如我要在天津的一台机器用三星 note跑测试,我要在成都的一台机器用 另外一台手机跑。

为了解决这个需求,我需要加入一个多配置的任务,然后在Configuration Matrix中进行配置,如图,把能够执行这个任务的多个节点给选上。

Configuration Matrix

如何合并多个cucumber报告

这里分两步,首先需要把每个节点的测试结果收集起来,然后传递到下游去,通过传递归档文件就可以完成这一步。比如我任务完成了之后会生成一个build目录,我需要把多台节点的这个目录传递过去。这里需要注意的点在于,每个节点生成的结果会加上自己的机器前缀。比如会像这样mac_chengdu/build,我们需要使用通配符 ****/build/**表示。

接下来是合并,因为cucumber生成的报告结果可以是json的,这一步就是在解析json的结果,我fork了cucumber-html-reporter对进行修改,做成了一个node的命令行工具,可以参考这里

关于自动化测试

iOS和安卓的开发中本身就提供单元测试的支持,比如iOS提供XCTest,安卓有JUnit,根据需要进行调整,比如iOS上我使用的Kiwi

单元测试比较简单,主要看团队对这东西的认识。主要聊一下功能测试这块遇到的坑。

先说iOS,iOS上采用的calabash,一个是项目组之前也在用,二个是我在调研了appium之后,发现appium最新版本才开始支持XCUITest做功能测试,存在一些bug且功能不够完善,因此果断上calabash。

在安卓遇到的坑相对来说多一点,首先calabash在安卓上底层是用的Instrumentation,调研过calabash的源码发现如果要让它支持UIAutomator的话,基本上等于重新造一个轮子了,因此如果你的产品不支持Instrumentation的话需要注意了。

那么appium呢,appium 配合cucumber在安卓上看起来不错的。我开开心心地用了起来,结果看报告发现这家伙在失败的时候不会主动截图,看样子得自己去实现了,好在cucumber提供了一些hook的方法,比如可以在每个执行步骤之后做点什么。 我一开始是在cucumber的AfterStep中加入了截图的方法,可是发现并没有什么用,后来查了一会儿发现已经有人给cucumber提过这个[issue](bundle exec cucumber #{feature}--tags ~@pending --format json --out #{BUILD_DIR}/functionals.json --format NewHtml --out #{BUILD_DIR}/functionals.html),原来cucumber设计上就是这样考虑的,失败了的步骤不允许hook。 既然cucumber这一层做不了,那只能在appium这一层做手脚了。经过观察,失败场景大多是找不到元素,因此我需要解决的主要问题是在找不到元素的时候进行截图。我在appium-lib中找到了driver.rb,看了下它提供了几个查找元素的方法,底层是用的selenium-webdriver进行操作,那么我的需求应该在driver这层就能够解决,我只需要在这几个方法执行失败后加上截图保存的方法就好了。Ruby我不熟悉,我查了下有几种方式可以解决,你可以新建一个子类重写这几个方法,你可以利用ruby的动态性把这几个方法给动态的替换了。我这里采用的是第二种方式,代码如下:

module DriverExtension
    def store_callback_after_fail(&block)
        @execute = block
    end

    def take_screenshot_when_fail
        @@screenshot_count ||= 0
        $filename = "./build/" + "Screenshot-" + "#{@@screenshot_count}" + ".png" 
        File.delete($filename) if File.exist?($filename)
        screenshot($filename)
        @execute.call($filename)
    end

    def find_element(*args)
        begin
            result = super 
            result
        rescue Exception => e
            take_screenshot_when_fail
            raise 
        end
    end

    ...
    ...
end

module Appium
    class Driver
        prepend DriverExtension
    end
end

采用流水线之后可以大幅度的减少人力成本,比如我们的客户之前还有安排同事专门负责构建打包上传等任务,代码出了问题也很难追溯到底在哪一步出了错。现在整个流程自动化了后,开发人员只需要更加专注于手中的开发任务,测试人员想什么时候测就什么时候测,要做的只需要点个按钮就好,是不是很赞!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 一关系图让你理解K8s中的概念,Pod、Service、Job等到底有啥关系

    刚开始接触K8s的同学可能都会觉得有一定的学习难度,扑面而来的各种概念到底是什么。比如,如何提供一个服务给别人,我是应该用Pod还是用Deployment来运行...

    100000798482
  • Functional Testing in iOS

    下面的Test Pyramid摘自Martin Fowler的 文章,越高层次产生的用户价值会更高且更慢,越低层次的产生的价值更低且更快,你所写的任何一行单元测...

    100000798482
  • 你是互联网的奴隶还是主宰者?

    这几天看了一本觉得还挺有点意思的书《浅薄:你是互联网的奴隶还是主宰者》,这本书并不是一本那么有趣的书,作者做了大量的科学调研为我们陈述了一个残酷的事实——我们逐...

    100000798482
  • 在线听歌房源码 - MKOnlineMusicPlayer V2.21

    Youngxj
  • Servlet3.0新特性(从注解配置到websocket编程)

         Servlet3.0的出现是servlet史上最大的变革,其中的许多新特性大大的简化了web应用的开发,为广大劳苦的程序员减轻了压力,提高了web开发...

    Single
  • 软件工程里的"重用"——从中台说起

    前段一个关于“中台”的文章被广为传转发,有挺中台的也有 dis 中台的。有朋友说,身边确实有需求要做这个的,你怎么看,有什么思路么。这里我就整理一下,大...

    崔秀龙
  • 设置 git/npm/bower/pip/gem镜像或代理

    有时候因为墙或者速度的原因使用git/npm/bower/pip/gem等工具的时候需要设置镜像或者代理,记录一下,不用到处找。 git 设置: $ ...

    Bob.Chen
  • Python 如何理解又晕又好用的装饰器

    Python 装饰器这东西对初学者来说是个坑,很容易绕晕,笔者当时初学装饰器时花费了数天时间,看了不同讲师对这块内容的讲解,还是一知半解。  

    py3study
  • 今天写了个蛋疼的弧形轮播图,怎么说也是原创了

    看到一个弧形轮播图的设计稿,脑子里突然闪现出一个蛋疼的实现方式,轮播的脚本就不用说了,我的HTML结构,恩,就是这样的: <!DOCTYPE html> <ht...

    练小习
  • 【Rust日报】 2019-11-01 - 2020年你期待的Rust是什么样子

    2019年接近尾声,2020年你对Rust有什么想法呢?写一篇博客然后在Twitter@rustlang,或者在Reddit r/rust频道上发表,总之让Ru...

    MikeLoveRust

扫码关注云+社区

领取腾讯云代金券