在Bamboo上怎么使用iOS的单元测试

本教程将使用北汽登录模块为例,一步一步和大家一起搭建单元测试用例,并在Bamboo上跑起来,最终测试结果和代码覆盖率会Bamboo上汇总。

模块名称:BQLoginModule,是通过iBiu创建的一个模块工程

72c5d67d270c4ed6a336eb2914b47d5a~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

一 建立单元测试Bundle

ProductName: BQLoginTests

f2c3c1cd7ba24bebb3010fafb1598412~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

二 测试代码编写

1 配置文件同步

如果我们要在测试代码使用我们在Pod里的类,需要同步 Targets Support Files/Pods-BQLoginTests/Pods-BQLoginTests.debug.xcconfig 文件的内容到 Targets Support Files/Pods-BQLoginUITests/Pods-BQLoginUITests.debug.xcconfig,直接内容copy就成了,只是每次用iBiu安装过后都要做这个操作,后续使用脚本实现同步:

74abc6c046324a069851a099a7d92453~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

2 测试代码编写

具体的编写我这里就过多介绍了,网上教程一大篇,这里就不多说了,如果没有做性能测试,这里可以把自动生成的 testPerformanceExample 屏蔽掉。 967f0f9fc05b4b06a97de4ec668b3744~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

三 运行单元测试

用 command+u,或者菜单(product->test)执行,就能获得结果

aaaa2cdd9fb34480b7796a46dbf142cd~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75 结果在这里看:

f85b0b6955bc4276ba1c46942a3c8f53~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

完成以上操作,基本的单元测试就OK了

下面我们用命令行来跑下单元测试,首先进入工程目录:

cd BQLoginModule/Example

执行如下命令:

xcodebuild test -UseModernBuildSystem=NO -configuration=Debug -workspace './BQLoginModule.xcworkspace' -scheme "BQLoginModule_Example" -destination 'platform=iOS Simulator,name=iPhone 8,OS=13.2.2' 

请大家注意将 workspace/scheme /模拟器信息 修改为自己工程对应信息

就可以看到结果

四 代码覆盖率

1 单元覆盖率

在XCode打开覆盖率统计,我们只打开我们的库做代码覆盖就成了,Xcode 12.4在如下地方:

765ebf1c4b914c09bbdbd5968b5f8f36~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75 在Pod里面BQLoginModule设置 BuildSettings 查找 "cov" ,把 以下2项都设置为YES;

6b2e959e19044b5081b1aab33c97fdb0~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75 然后我们跑下单元测试,就可以看到覆盖率结果了:

98815d3bcab24ea58513fe5e69f6f887~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

2 Bamboo报告

因为我们需要在Bamboo上汇总覆盖率报告,这里我们使用iBiu的一个高级特性:用 Podfile.custom 文件加载通用cocoapods的外网库来使用,具体见图:

57fbd2796da747eba243f1d57ede1a0b~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

这里我们引入2个库: OCMock(单元测试必备的Mock库) XcodeCoverage(覆盖率统计的库)

加入这个文件后,需要使用 iBou重新安装下组件

做如下设置:

9f0e1ad7b068430a9df8ef6d8796e69a~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

54a4fe63b74c4d91ba288a31d4bea83b~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

这个命令主要是生成XcodeCoverage的环境依赖 env.sh 我们打开文件看下,文件路径如下

cc7cc7e9fbc84e73a7cc6e65f9330e47~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

env.sh内容如下:

92d757b8d7f04f9095bbc607b7478bc1~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75 这里 OBJECT_FILE_DIR_normal 和 SRCROOT指向的是我们Example工程,我们是需要对Pods里的BQLoginModule里的代码做单元覆盖,这2个环境变量修改如下:

1export OBJECT_FILE_DIR_normal ="/Users/cdwutao3/Library/Developer/Xcode/DerivedData/BQLoginModule-fvrzeicgcswucwfgjqweugauzxia/Build/Intermediates.noindex/Pods.build/Debug-iphonesimulator/BQLoginModule.build/Objects-normal" 2 3export SRCROOT="/Users/cdwutao3/Desktop/ut/BQLoginModule/BQLoginModule/Classes"

然后在Pods/XcodeCoverage目录新建 xmlout目录,并运行命令:

./getcov -x -s -o xmlout 

可以得到如下结果:

68f9fe8f507145618fbf5d5bb03af6ae~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75 还可以查看哪些代码没被覆盖,和Bamboo结果对齐: d2c5038b23c148ecb2cab4b350fb641b~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75 完成以上步骤,就完成了本地用命令号完成单元测试的所有步骤,下面我们接着来看要在Bamboo上输出报告需要怎么做。

五 Bamboo操作

1 创建应用

这里要确保对应库和依赖的库 ,给 xn_testdev_ci账号开权限

f981fe262fc6406184b9cdc9cef7c98a~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

2 新建流水线

选择 “从零开始创建”

349e4e15da74498e83337d34378a807b~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

3 配置流水线

基础信息里面的选择如下

03a090b92db3479386c5e499813bbc73~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

3 配置流水线

de0ee41152a84a3a9778f4f381036481~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75 需要用到以下四个原子:

“下载代码” --大家可先配置使用“下载代码-iBiu”这个原子,我用这个一直使用不成功,所以直接用“下载代码”来手动配置: e956a4ec3c164de5a7442d12d3a5f860~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75 4a057a1e049242419d430f479f229f89~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75 “自定义脚本” --因为现在iOS的单元测试还没有对应的原子操作,所有我们通过自己写脚本来完成:

78f24206a4154aa7b865318921ca26a5~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

“单元测试” --你没看错,就是用java的单元测试原子,我们输出的结果和这个原子匹配,所以选他就成了

1c6268881a034aa3ae3c5872c9b0b08d~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75 7993348ddf7b4a759a62028efad68ed0~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

“GCC代码覆盖率” a0f3b2bf47bc4bda8266b0daca2ac858~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

9336147a3c844065bbc4e6d8a4ca6443~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75 其中“单元测试”和“代码覆盖率”的路径是可以修改的,这个可以根据自己的实际路径修改

4 自定义脚本

说明:

1 下载代码和配置iBiu都是自己的命令行来做的,但是需要开始配置下git用户信息

2 开始我用命令行写全部命令,但是Bamboo的命令行规则会导致一些的shell指令的失效,所以我采用把 shell命令 写到文件上传到git仓库,然后执行的方式来完成

3 结果转换会还会用到 ocunit2junit 和 xcpretty 这2个命令,如果这2个命令出错,请联系Bamboo同事协助安装下

4 大家在写shell命令时,不知道文件是否生成,可以多用 ls 来看目录下的文件

5 重点:

  • 为了手动安装iBiu配置,请将本机 ~/Library/Application Support/iBiu/BQLoginModule/下的2个文件 spec_sources 和 pod_setup 上传到git,我是copy到 Example/BQLoginModule/Resource目录下然后上传到git仓库,这个目录可以修改,然后修改对应shell 命令的目录就成了

  • iBiu建的git仓库默认会过滤一些内容,修改 BQLoginModule 工程目录下的 .gitignore 文件,需要上传xcworkspacedata内容

b266263ee6b248dca2bd22bf9724ac2b~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

  • 代码覆盖率设置,XcodeCoverage的说明强调了不要用于AppStore的工程,为了避免线上事故,我们通过命令来设置,不直接在工程里设置: a69fb07acea248129e59aa80ced8571c~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75 所以修改xcode的构建命令新加 GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES,命令如下:

    xcodebuild -UseModernBuildSystem=NO -enableCodeCoverage=YES -configuration=Debug GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES -workspace "./${moduleName}.xcworkspace" -scheme "${moduleName}_Example" -destination 'platform=iOS Simulator,name=iPhone 8,OS=13.2.2' test

5 Bamboo结果

8eab8c6eed3c44159fde0d4298b82611~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

覆盖率下载地址:

1d5d3d757a7e4434b1b712ea523265ee~tplv-73owjymdk6-jj-mark-v1_0_0_0_0_5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5Lqs5Lic5LqR5byA5Y-R6ICF_q75

六 脚本汇集

1 本地脚本

以BQLoginModule为例,最终本地脚本命令如下,大家可以重新找到本地目录执行查看效果:

1git clone --depth=1 https://git.jd.com/BQMobileshop/BQLoginModule.git 2cd BQLoginModule/Example 3pod update 4 5 6pwd 7moduleName="BQLoginModule" 8testName="BQLoginTests" 9 10 11biu -pod install ./ 12ls 13ls ./Pods 14rm -f "./Pods/Target Support Files/Pods-${testName}/Pods-${testName}.debug.xcconfig" 15cp -f "./Pods/Target Support Files/Pods-${moduleName}_Example/Pods-${moduleName}_Example.debug.xcconfig" "./Pods/Target Support Files/Pods-${testName}/Pods-${testName}.debug.xcconfig" 16cat "./Pods/Target Support Files/Pods-${testName}/Pods-${testName}.debug.xcconfig" 17 18 19xcodebuild clean -workspace "./${moduleName}.xcworkspace" -scheme "${moduleName}_Example" 20 21 22xcodebuild -UseModernBuildSystem=NO -enableCodeCoverage=YES -configuration=Debug GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES -workspace "./${moduleName}.xcworkspace" -scheme "${moduleName}_Example" -destination 'platform=iOS Simulator,name=iPhone 8,OS=13.2.2' test > utlogfile.txt 23cat utlogfile.txt |grep ".xcresult" > utlogpath.txt 24logStr=$(cat ./utlogpath.txt) 25logPath=${logStr:1} 26if [ -z "$logPath" ]; then 27 exit 1 28fi 29 30 31sed "s/${moduleName}.build/Debug-iphonesimulator/${moduleName}_Example.build/Pods.build/Debug-iphonesimulator/${moduleName}.build/g" ./Pods/XcodeCoverage/env.sh> cov_env1.txt 32sed "s/${moduleName}/Example/${moduleName}/${moduleName}/Classes/g" ./cov_env1.txt > cov_env2.txt 33cp -f ./Pods/XcodeCoverage/env.sh ./Pods/XcodeCoverage/env_bak.sh 34rm -f ./Pods/XcodeCoverage/env.sh 35cp ./cov_env2.txt ./Pods/XcodeCoverage/env.sh 36 37 38cat "./utlogfile.txt"|ocunit2junit 39ls test-reports 40 41 42cp ./cov_env2.txt ./Pods/XcodeCoverage/env.sh 43mkdir xmlout 44./Pods/XcodeCoverage/getcov -x -o xmlout 45ls ./xmlout/lcov 46 47 48cat "./utlogfile.txt"|xcpretty -t -r html --output testresult/testresult.html 49ls te

2 Bamboo脚本

Bamboo脚本分成2部分,一个是在Bamboo上执行的脚本

1rm -fr "/Users/admin/Library/Application Support/iBiu/BQLoginModule" 2mkdir "/Users/admin/Library/Application Support/iBiu/BQLoginModule" 3rm -fr ./BQLoginModule 4git clone --depth=1 https://git.jd.com/BQMobileshop/BQLoginModule.git 5cd BQLoginModule/Example 6cp "./BQLoginModule/Resource/spec_sources" "/Users/admin/Library/Application Support/iBiu/BQLoginModule" 7cp "./BQLoginModule/Resource/pod_setup" "/Users/admin/Library/Application Support/iBiu/BQLoginModule" 8ls "/Users/admin/Library/Application Support/iBiu/BQLoginModule" 9biu -pod install ./ 10 11 12sh UT.sh

脚本剩下部分写入 UT.sh,放在BQLoginModule/Example目录下, 然后上传到git仓库来执行,大家做的时候注意修改变量名称:

1pwd 2moduleName="BQLoginModule" 3testName="BQLoginTests" 4 5 6ls ./Pods 7rm -f "./Pods/Target Support Files/Pods-${testName}/Pods-${testName}.debug.xcconfig" 8cp -f "./Pods/Target Support Files/Pods-${moduleName}_Example/Pods-${moduleName}_Example.debug.xcconfig" "./Pods/Target Support Files/Pods-${testName}/Pods-${testName}.debug.xcconfig" 9cat "./Pods/Target Support Files/Pods-${testName}/Pods-${testName}.debug.xcconfig" 10 11 12xcodebuild clean -workspace "./${moduleName}.xcworkspace" -scheme "${moduleName}_Example" 13 14 15xcodebuild -UseModernBuildSystem=NO -enableCodeCoverage=YES -configuration=Debug GCC_INSTRUMENT_PROGRAM_FLOW_ARCS=YES GCC_GENERATE_TEST_COVERAGE_FILES=YES -workspace "./${moduleName}.xcworkspace" -scheme "${moduleName}_Example" -destination 'platform=iOS Simulator,name=iPhone 8,OS=13.2.2' test > utlogfile.txt 16cat utlogfile.txt |grep ".xcresult" > utlogpath.txt 17logStr=$(cat ./utlogpath.txt) 18logPath=${logStr:1} 19if [ -z "$logPath" ]; then 20 exit 1 21fi 22 23 24sed "s/${moduleName}.build/Debug-iphonesimulator/${moduleName}_Example.build/Pods.build/Debug-iphonesimulator/${moduleName}.build/g" ./Pods/XcodeCoverage/env.sh> cov_env1.txt 25sed "s/${moduleName}/Example/${moduleName}/${moduleName}/Classes/g" ./cov_env1.txt > cov_env2.txt 26cp -f ./Pods/XcodeCoverage/env.sh ./Pods/XcodeCoverage/env_bak.sh 27rm -f ./Pods/XcodeCoverage/env.sh 28cp ./cov_env2.txt ./Pods/XcodeCoverage/env.sh 29 30 31cat "./utlogfile.txt"|ocunit2junit 32ls test-reports 33 34 35cp ./cov_env2.txt ./Pods/XcodeCoverage/env.sh 36mkdir xmlout 37./Pods/XcodeCoverage/getcov -x -o xmlout 38ls ./xmlout/lcov 39 40 41cat "./utlogfile.txt"|xcpretty -t -r html --output testresult/testresult.html 42ls test

七 错误速查

这里汇集了在写脚本时的一些错误,方便大家查看

1 不能在测试工程引用自己的代码

请参看 二--1 ”配置文件同步“ 解决

2 在Bamboo上的Pods文件夹,没有拉到iBiu的其他配置信息

请参看 五--4 ”自定义脚本“的重点 1 来解决

3 “No coverage data in result bundle”

请参看 五--4 ”自定义脚本”的重点 2 来解决

4 使用命令行跑单元测试时,一直提示不能找到模拟器

-destination 'platform=iOS Simulator,name=iPhone 8,OS=13.2.2' 改为 -destination 'id=xxxxxxxxxx' 这种格式,id为屏幕提示

5 Bamboo Shell里提示 “未设置原子执行条件”

因为Bamboo的Shell对字符拼接,变量的处理有限制,所以一部分shell命令最好放在文件执行

6 在本地测试时,Pods/XXXXModule的设置项在每次iBiu安装后都会重置

请注意手动修改,或者直接使用脚本运行

7 在本地测试时,代码覆盖率只包含了一部分源码文件,不是全部

请清空 ~/Library/Developer/Xcode/DerivedData 目录再测试一次

8 在Bamboo上发现有些库拉不下来

请确保 对应 库给xn_testdev_ci开了权限

9 覆盖率文件生成不了

请确保XXXTests的版本信息和主工程的XXXXModule_Example的版本信息一致

点赞
收藏

评论区

加载中...

相关推荐

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

Demo002 IDEA中Junit单元测试的使用(初级篇)

推荐JUnit视频教程:JUnit—Java单元测试必备工具(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fwww.imooc.com%2Flearn%2F356)。1.基本理论1.1单元测试单元测试又称模块测试,属于白盒测试,是最小单位的测试。模

Scapy 从入门到放弃

0x00前言最近闲的没事,抽空了解下地表最强的嗅探和收发包的工具:scapy。scapy是一个python模块,使用简单,并且能灵活地构造各种数据包,是进行网络安全审计的好帮手。0x01安装因为2020年python官方便不再支持python2,所以使用python3安装。!(https://oscimg.oschina.net/os

FLV文件格式

1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.