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

news2024/9/20 18:44:09

作者:京东零售 吴滔

本教程将使用北汽登录模块为例,一步一步和大家一起搭建单元测试用例,并在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.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的版本信息一致

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/512313.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅尝Kubernetes

第一节 内容编排与Kubernetes 为什么要用k8s 集群环境容器部署的困境,假设我们有数十台服务器。分别部署Nginx,redis,mysql,业务服务。如何合理的分配这些资源。这里就需要用到容器编排 容器编排 在实际集群环境下&#xff0…

JAVA-抽象类和接口

文章目录 前言 大家好呀,今天给大家带来抽象类和接口的讲解,那么废话不多说,跟着我一起去学习吧! 1.1抽象类的概念 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果 一个类…

Java 11新特性:模块化系统和本地变量类型推断

作为Java语言的最新版本,Java 11带来了许多新特性,其中最引人注目的是模块化系统和本地变量类型推断。这两个新特性对Java开发人员来说具有重要意义,因此在本文中,我们将详细探讨这两个新特性及其对Java开发的影响。 章节1&#…

记录一次uniapp实现APP自动升级

描述 app的版本管理和升级,是一个不可或缺的功能,而uniapp则是提供了一整套的流程,由于官方文档过于复杂,而且写的云里雾里的,所以个人记录一次我的操作,直到配置成功。 总体 一共分为2个部分&#xff0…

scanf与printf函数的用法

前言: 学习c语言编程,必不可少的操作就是键盘输入与屏幕输出。今天我想讲讲自己对scanf与printf使用的看法 一、scanf与printf: 1.scanf()函数: int scanf ( const char * format, ... ); 函数的功能:从标准输入中…

契约锁亮相华为2023中国合作伙伴大会,共谱华为云软件生态新篇章

5月8日-9日,以“因聚而生 众志有为”为主题的“华为中国合作伙伴大会2023”在深圳举行。契约锁作为华为云优秀软件伙伴,受邀参会并在“聚数字化先行者,谱软件生态新乐章”分论坛开展“让数字可信,打通数字化最后一公里”数字化实践…

Google Play 政策更新重点回顾 (下) | 2023 年 4 月

Google Play 和您一样,始终坚持为用户提供更优质的产品、更流畅的体验。为持续打造值得信赖的优质应用平台,我们也在不断进行政策更新。在上一篇文章中与您回顾了 2023 年 4 月 Google Play 政策的更新要点,这篇文章我们将为您带来重点政策解…

golang汇编之常量和全局变量(三)

常量 Go汇编语言中常量以$美元符号为前缀。常量的类型有整数常量、浮点数常量、字符常量和字符串常量等几种类型。以下是几种类型常量的例子: $1 // 十进制 $0xf4f8fcff // 十六进制 $1.5 // 浮点数 $a // 字符 $"abcd" …

【加解密篇】Passware Kit Forensic暴力美学-已知部分密码自定义解密详细参数设置

【加解密篇】Passware Kit Forensic暴力美学-已知部分密码自定义解密详细参数设置 都说"自制武器不一定是最强的,但最强的武器一定是自制的",对于取证工具也是一样,虽然默认配置足够强,但如果我们能根据实时情景自定义…

arduino 导入 Brain 库

一、引言 最近在做一个可以用脑电波控制的arduino小车,需要用到Brain这个库,而且需要自己导入才能使用。之前试了很多方法,导入成功了,过了几个月又忘记怎么导入了,今天想起来记录一下,好记性不如烂笔头。 …

LNK2019 无法解析的外部符号,一种新的思路

LNK2019 无法解析的外部符号,一种新的思路 一般来说,这种问题的原因有如下几点: 函数只有声明没有实现如果是其它库的函数,可能没有链接lib文件如果函数是封装在dll中的,可能没有导出如果是模板函数或模板类&#xf…

初始MyBatis,w字带你解MyBatis

一.什么是mybatis mybatis的概念 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。1、Mybatis是一个半ORM(对象关系映射)框架,底层封装了JDBC,是程序员在开发时只需要关注SQL语句本身&#…

U-boot顶层Makefile文件分析(一)

在阅读 uboot 源码之前,肯定是要先看一下顶层 Makefile,分析 gcc 版本代码的时候一定是先从顶层 Makefile 开始的,然后再是子 Makefile,这样通过层层分析 Makefile 即可了解整个工程的组织结构。顶层 Makefile 也就是 uboot 根目录…

界面控件DevExpress WPF MessageBox组件,进一步增强用户体验!

在DevExpress WPF v22.2版本中,官方引入了一系列功能来帮助改进一个常见WPF UI元素——MessageBox的用户体验,新的MessageBox相关选项包括: 文本选择支持自定义图像支持带有计时器的按钮,可以自动关闭窗口 ThemedMessageBox类允…

OJ练习第103题——最大矩形

最大矩形 力扣链接:85. 最大矩形 题目描述 给定一个仅包含 0 和 1 、大小为 rows x cols 的二维二进制矩阵,找出只包含 1 的最大矩形,并返回其面积。 示例 输入:matrix [[“1”,“0”,“1”,“0”,“0”],[“1”,“0”,“1”…

数据库管理-第七十四期 我的Oracle ACE之路(20230511)

数据库管理 2023-05-11 第七十四期 我的Oracle ACE之路1 差点错过2 ACE Associate3 一路走来总结 第七十四期 我的Oracle ACE之路 “终于等到你,还好我没放弃”。经过了整整4个月20天的等待,我终于收到了Oracle ACE Associate的确认邮件,成为…

『python爬虫』17. 线程池和进程池以及线程池实战(保姆级图文)

目录 1. 线程池和进程池解决的是调度问题2. 线程池3. 线程池实战:爬取西游记的标题总结 欢迎关注 『python爬虫』 专栏,持续更新中 欢迎关注 『python爬虫』 专栏,持续更新中 1. 线程池和进程池解决的是调度问题 ⽹站的数据太多了&#xff0…

典型随机噪声激励

1.按噪声的起源分类 根据噪声的起源,分为内部噪声和外部噪声。 内部噪声:来源于系统内部的涨落运动或被检测信号,如布朗粒子受到周围液体分子的无规则碰撞即为内部噪声; 外部噪声:来自系统所处外部环境的随机涨落&…

endNote X9 导入英文文献(谷歌学术、web of science 等)

文章目录 1 导入英文文献(谷歌学术、web of science 等)2 EndNote X9 插入参考文献常见问题总结3 EndNote X9 快速上手教程(毕业论文参考文献管理器) 1 导入英文文献(谷歌学术、web of science 等) 谷歌学术…

Vite如何实现秒级依赖预构建的能力

大家都知道, Vite是一个提倡 no-bundle 的构建工具,相比于传统的 Webpack,能做到开发时的模块按需编译,而不用先打包完再加载。这一点我们在快速上手这一节已经具体地分析过了。 需要注意的是,我们所说的模块代码其实分为两部分,一部分是源代码,也就是业务代码,另一部…