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

作者: 一个大番茄 | 来源:发表于2016-11-28 14:22 被阅读502次

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

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

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

    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
    

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

    相关文章

      网友评论

        本文标题:移动开发流水线建立以及自动化测试

        本文链接:https://www.haomeiwen.com/subject/manrpttx.html