(四) 使用Travis CI集成单元测试

前言

git pre-push hook 实践一二 一文中,我们实践了如何使用pre-hook执行单元测试以影响push操作的结果。但这种方式也有不少缺点,如无法hook pr,无法在提交版本里记录和共享显示测试的结果。Travis CI作为github官方支持的service,免费为开源项目提供了一个优秀的持续集成环境。关于Travis CI的简介和使用,可以参考这篇 EyreFree: 利用 Travis CI 让你在 GitHub 上的 Xcode 项目持续构建。下面,我们将简介如何集成iOS的单元测试和测试的代码覆盖率工具。

单元测试

我们已经知道,在工程目录下执行xcodebuild test命令,可以启动xcode 的单元测试,在持续集成环境下依然如此。在根目录的.travis.yml文件中配置相关操作。

.travis.yml
osx_image: xcode9
language: objective-c

cache: cocoapods
podfile: Example/Podfile

env:
  global:
    - LANG=en_US.UTF-8
    - LC_ALL=en_US.UTF-8
    - WORKSPACE_NAME=`sudo find ./Example -name "*.xcworkspace" -maxdepth 1 |while read var; do echo $(basename $var .xcworkspace); done`
    # the file named '*.xcworkspace' should be created by 'pod lib create...'

before_install:
  - gem install xcpretty --no-rdoc --no-ri --no-document --quiet
  - gem install cocoapods --pre --no-rdoc --no-ri --no-document --quiet
  #- gem install slather --pre --no-rdoc --no-ri --no-document --quiet
  - pod install --project-directory=Example
  - rvm use $RVM_RUBY_VERSION

script:
  - set -o pipefail
  - echo $WORKSPACE_NAME
  #- xcodebuild -workspace "$XCODE_WORKSPACE" -scheme "$SCHEME" -configuration Debug clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcpretty -c
  #- xcodebuild -workspace "$XCODE_WORKSPACE" -scheme "$SCHEME" -configuration Release clean build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO | xcpretty -c
  - xcodebuild test -enableCodeCoverage YES -workspace Example/$WORKSPACE_NAME.xcworkspace -scheme $WORKSPACE_NAME-Example -destination 'platform=iOS Simulator,OS=latest,name=iPhone 8'  -destination 'platform=iOS Simulator,OS=10.3.1,name=iPhone 7' -destination 'platform=iOS Simulator,OS=9.3,name=iPhone 6s'
  - pod lib lint --allow-warnings --verbose

after_success:
  - slather
  - bash <(curl -s https://codecov.io/bash) #-f Example/cobertura.xml -X coveragepy -X gcov -X xcode -t
  - sleep 3

xcodebuild test
 - xcodebuild test -enableCodeCoverage YES -workspace Example/$WORKSPACE_NAME.xcworkspace -scheme $WORKSPACE_NAME-Example 
 -destination 'platform=iOS Simulator,OS=latest,name=iPhone 8'  
 -destination 'platform=iOS Simulator,OS=10.3.1,name=iPhone 7' 
 -destination 'platform=iOS Simulator,OS=9.3,name=iPhone 6s'

以上代码会在三个不同的destination上进行单元测试并产生代码覆盖率记录,iOS11可选择最新的系统版本,较旧版本可以在环境提供的列表中选择。对于cocoapods创建的包含demo的库,可以使用sudo find ./Example -name "*.xcworkspace" -maxdepth 1 |while read var; do echo $(basename $var .xcworkspace); done 自动确定workspace的文件名及补全scheme,这对统一快捷配置CI的yml文件是有益的,当然,我们也可以自己手动配置与工程名及路径相关的参数。

测试结果日志
屏幕快照 2017-12-19 下午5.07.11.png
pr操作页-check结果为成功
1.png
pr操作页-check结果为失败
2.png

test failed时,整体会exit with 0,check为失败。此外,pod lib lint操作等也会影响check结果。这对审阅者合并pr有一定的参考意义。

测试的代码覆盖率

运行编写的测试用例时,可能存在以下情况: 某个方法的if/switch分支没有执行到,甚至某个类的整个方法未被调用。这就形成了
所谓的测试覆盖率问题,可靠有效的测试结果应该建立在足够高代码覆盖率的测试用例上。下面介绍三种查看测试覆盖率的方式。

1. xcode

当test设置勾上code coveragexcodebuild test -enableCodeCoverage YES时,将产生覆盖率记录文件。

勾选代码覆盖

3.png

如上图,我们可以查看到所有文件的代码覆盖率。点击类名,可以查看到标红即未被覆盖到的代码。

4.png

2. Slather

Generate test coverage reports for Xcode projects & hook it into CI.

slather是一个专业用于xcode生成测试代码覆盖率报告的工具。安装可参见github。当我们运行单元测试后,可在根目录执行:

slather coverage  --scheme LPDCNetwork-Example 
--workspace Example/LPDCNetwork.xcworkspace Example/LPDCNetwork.xcodeproj

结果为:

5.png

也可以执行:

$ slather coverage --html --show  
--scheme LPDCNetwork-Example --workspace ./LPDCNetwork.xcworkspace ./LPDCNetwork.xcodeproj

自动生成并打开html形式的覆盖率报告。

6.png

另外,可以调整工程目录结构和修改.slather.yml文件配置,执行slather在自定义目录下生成覆盖率的xml文件,可用于上传到一些覆盖率服务生成报告集成pr界面。可用--ignore命令或yml文件ignre下配置忽略不计入平均覆盖率的文件路径。

.slather.yml
coverage_service: cobertura_xml
workspace: Example/PopoverObjC.xcworkspace
xcodeproj: Example/PopoverObjC.xcodeproj
scheme: PopoverObjC-Example
source_directory: Example/
output_directory: Example/
ignore:

3. codecov

codecov对github有着良好的支持,当我们在CI中执行完单元测试后,可执行如下代码自动上传xcode代码覆盖率文件,或者上传前文slather相关命令生成的xml文件。

bash <(curl -s https://codecov.io/bash) #-f Example/cobertura.xml -X coveragepy -X gcov -X xcode -t

日志:

3.93s$ bash <(curl -s https://codecov.io/bash)
==> Travis CI detected.

    project root: .

    Yaml not found, that is ok! Learn more at http://docs.codecov.io/docs/codecov-yaml

==> Processing Xcode plists

    Found plist file at /Users/travis/Library/Developer/Xcode/DerivedData/PopoverObjC-byqecvztvcxucabbetxyjvpkugpa/Logs/Test/E6D08998-FE45-47F6-B63C-1A81F39A7CF5.xccoverage

==> Running gcov in . (disable via -X gcov)

==> Python coveragepy not found

==> Searching for coverage reports in:

    + .

    -> Found 4 reports

==> Detecting git/mercurial file structure

==> Appending build variables

    + TRAVIS_OS_NAME

    + TRAVIS_RUBY_VERSION

==> Reading reports

    + ./344206B7-9176-4963-8C93-EE67C319FEE8.xccoverage.plist bytes=13127261

    + ./DD06A5DE-7636-4E63-BC90-A70235D4E1D2.xccoverage.plist bytes=222002

    + ./E6D08998-FE45-47F6-B63C-1A81F39A7CF5.xccoverage.plist bytes=221932

    + ./Example/cobertura.xml bytes=6036

==> Appending adjustments

    http://docs.codecov.io/docs/fixing-reports

    + Found adjustments

==> Gzipping contents

==> Uploading reports

    url: https://codecov.io

    query: branch=testCI&commit=98933100ae86b02345de549f28783167d6ce3ebc&build=99.1&build_url=&name=&tag=&slug=Assuner-Lee%2FPopoverObjC&service=travis&flags=&pr=false&job=318459810

    -> Pinging Codecov

    -> Uploading

    -> View reports at https://codecov.io/github/Assuner-Lee/PopoverObjC/commit/98933100ae86b02345de549f28783167d6ce3ebc

覆盖率报告:

7.png
8.png
9.png

覆盖率报告的信息还是很丰富的,可以得到每个commit的覆盖率数值,各个分支间的对比,相比于基准值的对比等。此外,我们同样可以在codecov.yml文件中设置要忽略的文件路径,以得到更准确的平均覆盖率。

同样,在pr页面可以看到codecov的覆盖率概览报告。

10.png

通过CI集成单元测试及代码覆盖率、lint等结果信息到pull,pr页面,这对于代码审阅,控制代码质量有着一定的积极作用。

谢谢观看,水平有限,如有错误,请多指教。

参考资料:

https://juejin.im/post/5a32154e51882503dc53b976

https://github.com/SlatherOrg/slather

系列文章

(一) 初探 iOS 单元测试

(二) kiwi 实践一二

(三) git pre-push hook 实践一二

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

推荐阅读更多精彩内容