作者:京东零售吴滔

教程将运用北汽登录模块为例,一步一步和咱们一起树立单元测验用例,并在Bamboo上跑起来,最终测验成果和代码掩盖率会Bamboo上汇总。

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

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

一 树立单元测验Bundle

ProductName: BQLoginTests

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

二 测验代码编写

1 装备文件同步

如果咱们要在测验代码运用咱们在Pod里的类,需求同步 Targets Support Files/Pods-BQLoginTests/Pods-BQLoginTests.debug.xcconfig 文件的内容到 Targets Support Files/Pods-BQLoginUITests/Pods-BQLoginUITests.debug.xcconfig,直接内容copy就成了,仅仅每次用iBiu装置过后都要做这个操作,后续运用脚本完结同步:

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

2 测验代码编写

详细的编写我这儿就过多介绍了,网上教程一大篇,这儿就不多说了,如果没有做功能测验,这儿能够把主动生成的 testPerformanceExample 屏蔽掉。

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

三 运转单元测验

用 command+u,或许菜单(product->test)履行,就能取得成果

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

成果在这儿看:

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

完结以上操作,根本的单元测验就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在如下当地:

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

在Pod里边BQLoginModule设置 BuildSettings 查找 “cov” ,把 以下2项都设置为YES;

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

然后咱们跑下单元测验,就能够看到掩盖率成果了:

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

2 Bamboo陈述

由于咱们需求在Bamboo上汇总掩盖率陈述,这儿咱们运用iBiu的一个高级特性:用 Podfile.custom 文件加载通用cocoapods的外网库来运用,详细见图:

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

这儿咱们引进2个库: OCMock(单元测验必备的Mock库) XcodeCoverage(掩盖率计算的库)

加入这个文件后,需求运用 iBou从头装置下组件

做如下设置:

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

这个指令主要是生成XcodeCoverage的环境依靠 env.sh 咱们翻开文件看下,文件途径如下

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

env.sh内容如下:

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

这儿 OBJECT_FILE_DIR_normal 和 SRCROOT指向的是咱们Example工程,咱们是需求对Pods里的BQLoginModule里的代码做单元掩盖,这2个环境变量修正如下:

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

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

./getcov -x -s -o xmlout

能够得到如下成果:

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

还能够检查哪些代码没被掩盖,和Bamboo成果对齐:

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

完结以上过程,就完结了本地用指令号完结单元测验的所有过程,下面咱们接着来看要在Bamboo上输出陈述需求怎么做。

五 Bamboo操作

1 创立应用

这儿要保证对应库和依靠的库 ,给 xn_testdev_ci账号开权限

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

2 新建流水线

挑选 “从零开端创立”

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

3 装备流水线

基础信息里边的挑选如下

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

需求用到以下四个原子:

“下载代码”–咱们可先装备运用“下载代码-iBiu”这个原子,我用这个一直运用不成功,所以直接用“下载代码”来手动装备:

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

“自定义脚本”–由于现在iOS的单元测验还没有对应的原子操作,所有咱们通过自己写脚本来完结:

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

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

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

“GCC代码掩盖率”

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

其间“单元测验”和“代码掩盖率”的途径是能够修正的,这个能够依据自己的实际途径修正

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内容

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

  • 代码掩盖率设置,XcodeCoverage的说明强调了不要用于AppStore的工程,为了防止线上事端,咱们通过指令来设置,不直接在工程里设置:

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

所以修正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成果

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

掩盖率下载地址:

在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队

六 脚本汇集

1 本地脚本

以BQLoginModule为例,最终本地脚本指令如下,咱们能够从头找到本地目录履行检查作用:

git clone --depth=1 https://git.jd.com/BQMobileshop/BQLoginModule.git
cd BQLoginModule/Example
pod update
pwd
moduleName="BQLoginModule"
testName="BQLoginTests"
biu -pod install ./
ls
ls ./Pods
rm -f "./Pods/Target Support Files/Pods-${testName}/Pods-${testName}.debug.xcconfig"
cp -f "./Pods/Target Support Files/Pods-${moduleName}_Example/Pods-${moduleName}_Example.debug.xcconfig"  "./Pods/Target Support Files/Pods-${testName}/Pods-${testName}.debug.xcconfig"
cat "./Pods/Target Support Files/Pods-${testName}/Pods-${testName}.debug.xcconfig"
xcodebuild clean -workspace "./${moduleName}.xcworkspace" -scheme "${moduleName}_Example"
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  > utlogfile.txt
cat utlogfile.txt |grep ".xcresult" > utlogpath.txt
logStr=$(cat ./utlogpath.txt)
logPath=${logStr:1}
if [ -z "$logPath" ]; then
	exit 1
fi
sed "s/${moduleName}.build\/Debug-iphonesimulator\/${moduleName}_Example.build/Pods.build\/Debug-iphonesimulator\/${moduleName}.build/g" ./Pods/XcodeCoverage/env.sh> cov_env1.txt
sed "s/${moduleName}\/Example/${moduleName}\/${moduleName}\/Classes/g" ./cov_env1.txt > cov_env2.txt
cp -f ./Pods/XcodeCoverage/env.sh ./Pods/XcodeCoverage/env_bak.sh
rm -f ./Pods/XcodeCoverage/env.sh
cp ./cov_env2.txt ./Pods/XcodeCoverage/env.sh
cat "./utlogfile.txt"|ocunit2junit
ls test-reports
cp ./cov_env2.txt ./Pods/XcodeCoverage/env.sh
mkdir xmlout
./Pods/XcodeCoverage/getcov -x -o xmlout
ls ./xmlout/lcov
cat "./utlogfile.txt"|xcpretty -t -r html --output testresult/testresult.html
ls te

2 Bamboo脚本

Bamboo脚本分红2部分,一个是在Bamboo上履行的脚本

rm -fr "/Users/admin/Library/Application Support/iBiu/BQLoginModule"
mkdir "/Users/admin/Library/Application Support/iBiu/BQLoginModule"
rm -fr ./BQLoginModule
git clone --depth=1 https://git.jd.com/BQMobileshop/BQLoginModule.git
cd BQLoginModule/Example
cp "./BQLoginModule/Resource/spec_sources" "/Users/admin/Library/Application Support/iBiu/BQLoginModule"
cp "./BQLoginModule/Resource/pod_setup" "/Users/admin/Library/Application Support/iBiu/BQLoginModule"
ls "/Users/admin/Library/Application Support/iBiu/BQLoginModule"
biu -pod install ./
sh UT.sh

脚本剩余部分写入 UT.sh,放在BQLoginModule/Example目录下, 然后上传到git库房来履行,咱们做的时分留意修正变量名称:

pwd
moduleName="BQLoginModule"
testName="BQLoginTests"
ls ./Pods
rm -f "./Pods/Target Support Files/Pods-${testName}/Pods-${testName}.debug.xcconfig"
cp -f "./Pods/Target Support Files/Pods-${moduleName}_Example/Pods-${moduleName}_Example.debug.xcconfig"  "./Pods/Target Support Files/Pods-${testName}/Pods-${testName}.debug.xcconfig"
cat "./Pods/Target Support Files/Pods-${testName}/Pods-${testName}.debug.xcconfig"
xcodebuild clean -workspace "./${moduleName}.xcworkspace" -scheme "${moduleName}_Example"
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  > utlogfile.txt
cat utlogfile.txt |grep ".xcresult" > utlogpath.txt
logStr=$(cat ./utlogpath.txt)
logPath=${logStr:1}
if [ -z "$logPath" ]; then
	exit 1
fi
sed "s/${moduleName}.build\/Debug-iphonesimulator\/${moduleName}_Example.build/Pods.build\/Debug-iphonesimulator\/${moduleName}.build/g" ./Pods/XcodeCoverage/env.sh> cov_env1.txt
sed "s/${moduleName}\/Example/${moduleName}\/${moduleName}\/Classes/g" ./cov_env1.txt > cov_env2.txt
cp -f ./Pods/XcodeCoverage/env.sh ./Pods/XcodeCoverage/env_bak.sh
rm -f ./Pods/XcodeCoverage/env.sh
cp ./cov_env2.txt ./Pods/XcodeCoverage/env.sh
cat "./utlogfile.txt"|ocunit2junit
ls test-reports
cp ./cov_env2.txt ./Pods/XcodeCoverage/env.sh
mkdir xmlout
./Pods/XcodeCoverage/getcov -x -o xmlout
ls ./xmlout/lcov
cat "./utlogfile.txt"|xcpretty -t -r html --output testresult/testresult.html
ls 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的版别信息共同