写点什么

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

  • 2023-05-11
    北京
  • 本文字数:4814 字

    阅读完需:约 16 分钟

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

作者:京东零售 吴滔


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


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


一 建立单元测试 Bundle

ProductName: BQLoginTests


二 测试代码编写

1 配置文件同步

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


2 测试代码编写

具体的编写我这里就过多介绍了,网上教程一大篇,这里就不多说了,如果没有做性能测试,这里可以把自动生成的 testPerformanceExample 屏蔽掉。


三 运行单元测试

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



结果在这里看:



完成以上操作,基本的单元测试就 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 在如下地方:



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



然后我们跑下单元测试,就可以看到覆盖率结果了:


2 Bamboo 报告

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



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


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


做如下设置:




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



env.sh 内容如下:



这里 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 结果对齐:



完成以上步骤,就完成了本地用命令号完成单元测试的所有步骤,下面我们接着来看要在 Bamboo 上输出报告需要怎么做。

五 Bamboo 操作

1 创建应用

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


2 新建流水线

选择 “从零开始创建”


3 配置流水线

基础信息里面的选择如下




需要用到以下四个原子:


“下载代码”--大家可先配置使用“下载代码-iBiu”这个原子,我用这个一直使用不成功,所以直接用“下载代码”来手动配置:




“自定义脚本”--因为现在 iOS 的单元测试还没有对应的原子操作,所有我们通过自己写脚本来完成:



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




“GCC 代码覆盖率”




其中“单元测试”和“代码覆盖率”的路径是可以修改的,这个可以根据自己的实际路径修改

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



  • 代码覆盖率设置,XcodeCoverage 的说明强调了不要用于 AppStore 的工程,为了避免线上事故,我们通过命令来设置,不直接在工程里设置:



所以修改 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 结果


覆盖率下载地址:


六 脚本汇集

1 本地脚本

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


git clone --depth=1 https://git.jd.com/BQMobileshop/BQLoginModule.gitcd BQLoginModule/Examplepod update

pwdmoduleName="BQLoginModule"testName="BQLoginTests"

biu -pod install ./lsls ./Podsrm -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.txtcat utlogfile.txt |grep ".xcresult" > utlogpath.txtlogStr=$(cat ./utlogpath.txt)logPath=${logStr:1}if [ -z "$logPath" ]; then exit 1fi

sed "s/${moduleName}.build\/Debug-iphonesimulator\/${moduleName}_Example.build/Pods.build\/Debug-iphonesimulator\/${moduleName}.build/g" ./Pods/XcodeCoverage/env.sh> cov_env1.txtsed "s/${moduleName}\/Example/${moduleName}\/${moduleName}\/Classes/g" ./cov_env1.txt > cov_env2.txtcp -f ./Pods/XcodeCoverage/env.sh ./Pods/XcodeCoverage/env_bak.shrm -f ./Pods/XcodeCoverage/env.shcp ./cov_env2.txt ./Pods/XcodeCoverage/env.sh

cat "./utlogfile.txt"|ocunit2junitls test-reports

cp ./cov_env2.txt ./Pods/XcodeCoverage/env.shmkdir xmlout./Pods/XcodeCoverage/getcov -x -o xmloutls ./xmlout/lcov

cat "./utlogfile.txt"|xcpretty -t -r html --output testresult/testresult.htmlls 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 ./BQLoginModulegit clone --depth=1 https://git.jd.com/BQMobileshop/BQLoginModule.gitcd BQLoginModule/Examplecp "./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 仓库来执行,大家做的时候注意修改变量名称:


pwdmoduleName="BQLoginModule"testName="BQLoginTests"

ls ./Podsrm -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.txtcat utlogfile.txt |grep ".xcresult" > utlogpath.txtlogStr=$(cat ./utlogpath.txt)logPath=${logStr:1}if [ -z "$logPath" ]; then exit 1fi

sed "s/${moduleName}.build\/Debug-iphonesimulator\/${moduleName}_Example.build/Pods.build\/Debug-iphonesimulator\/${moduleName}.build/g" ./Pods/XcodeCoverage/env.sh> cov_env1.txtsed "s/${moduleName}\/Example/${moduleName}\/${moduleName}\/Classes/g" ./cov_env1.txt > cov_env2.txtcp -f ./Pods/XcodeCoverage/env.sh ./Pods/XcodeCoverage/env_bak.shrm -f ./Pods/XcodeCoverage/env.shcp ./cov_env2.txt ./Pods/XcodeCoverage/env.sh

cat "./utlogfile.txt"|ocunit2junitls test-reports

cp ./cov_env2.txt ./Pods/XcodeCoverage/env.shmkdir xmlout./Pods/XcodeCoverage/getcov -x -o xmloutls ./xmlout/lcov

cat "./utlogfile.txt"|xcpretty -t -r html --output testresult/testresult.htmlls 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 的版本信息一致

发布于: 刚刚阅读数: 3
用户头像

拥抱技术,与开发者携手创造未来! 2018-11-20 加入

我们将持续为人工智能、大数据、云计算、物联网等相关领域的开发者,提供技术干货、行业技术内容、技术落地实践等文章内容。京东云开发者社区官方网站【https://developer.jdcloud.com/】,欢迎大家来玩

评论

发布
暂无评论
在Bamboo上怎么使用iOS的单元测试 | 京东云技术团队_ios_京东科技开发者_InfoQ写作社区