xcode进行代码覆盖率测试
去年写的文章,搬到cnblog
本文所述的方法只对xcode5做过测试,xcode6是否可行尚未可知。
配置编译选项
首先请参考苹果官方的文档Configuring Xcode for Code Coverage进行相依的编译选项配置,以生成最基所需的基础数据。为了区别与Release&Debug的版本,建议新建一个叫做Coverage(任何名字都行)编译配置Configuration(从Debug Copy),方法在上面的文档里面有说明。
对这个Coverage编译选项,做如下配置:(仅对Coverage做修改,不要影响到原来的Debug,Release以及Distribution
Generate Debug Symbols配置成YES
Generate Test Coverage Files配置成YES
Instrument Program Flow配置成YES做了上面的配置以后,如果为模拟器编译Coverage版本,那么可以看到~/Library/Developer/Xcode/DerivedData/{project_dir}/Build/Intermediates/{target_name}.build/Coverage-iphonesimulator/{target-name}.build/Objects-normal/i386下面,有一些.gcno文件。
收集运行时数据
程序运行的时候,会自动记录覆盖率相关的数据,但是这个数据只有在程序正常退出的时候才会写到文件。对于OS X程序来说,只要通过Quit菜单退出即可;
对与ios程序来说,要想正常的退出app,只有将info.plist里面的UIApplicationExitsOnSuspend置为YES,这样按home键就退出了,但这种方法需要干扰正常的应用逻辑,不利于维护;
第二种方式是通过添加代码,只要在AppDelegate里面添加这样的代码即可:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
#if NT_COVERAGE
extern void __gcov_flush(void);
__gcov_flush();
#endif
}
NT_COVERAGE是一个自定义的宏,建议在主taget的Build Setting/Preprocessor Macros为Coverage配置添加一个宏`NT_COVERAGE=1`,这样通过这个宏可以用来过滤这些专门为覆盖率测试所写的代码片段。
以模拟器为例,将app运行起来,进行一些操作,最后切换到后台,此时~/Library/Developer/Xcode/DerivedData/{project_dir}/Build/Intermediates/{target_name}.build/Coverage-iphonesimulator/{target-name}.build/Objects-normal/i386下应该有一些.gcda文件。
转换数据
这一步是将收集的数据转换成可读的形式,使用一个开源库XcodeCoverage可以完美做到这一点:得到一组html文件,可以方便地产看每个目录下的每个类,每个函数的执行情况。
请按照这个链接所指向的文章的指示进行配置。
这个开源库就是一些脚本及几个很小的可执行文件,建议直接放在project的目录下即可。脚本下面的getcov是个bash脚本,可以进行一些必要的修改:
1)、exclude_data函数里面,可以排除一些不想统计覆盖率的代码
假设一些第三方库都位于library子目录,可以这样来排除
LCOV --remove ${LCOV_INFO} "library/*" -d "${OBJ_DIR}" -o ${LCOV_INFO}2)、generate_report函数里面,可以更改产生html的目录
我是这么改的,在文件的头部增加 REPORT_DIR=${DIR}/report,指定html的目录为XcodeCoverage/report
generage_report被改成:
generate_report()
{
"${LCOV_PATH}/genhtml" --output-directory “${REPORT_DIR}” ${LCOV_INFO}
cd ${REPORT_DIR}
open index.html
}
当完成数据收集后,运行./getcov命令即可。
- 如何针对ios设备进行覆盖率测试
与模拟器相比,区别的地方在于测试数据输出的位置,因为默认的位置在设备上是不可写的,因此需要在appDelegate里面做一些修改:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
#if NT_COVERAGE
#if !TARGET_IPHONE_SIMULATOR
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
setenv("GCOV_PREFIX", [documentsDirectory cStringUsingEncoding:NSUTF8StringEncoding], 1);
setenv("GCOV_PREFIX_STRIP", "13", 1);
#endif
extern void __gcov_flush(void);
__gcov_flush();
#endif
}
第一个setenv的意思是将数据的根目录设置为app的Documents;
第二个setenv的意思是strip掉一些目录层次,因为覆盖率数据默认会写入一个很深的目录层次。
在完成app测试之后,将这些.gcda文件拷贝到对应.gcno文件同样的目录,在我的测试case下是~/Library/Developer/Xcode/DerivedData/{project_dir}/Build/Intermediates/{target_name}.build/Coverage-iphoneos/{target-name}.build/Objects-normal/armv7。然后运行上面3中getcov命令即可。
与单元测试相结合
XcodeCoverage介绍了如何在单元测试后自动生成覆盖率测试报告,只是一个脚本配置而已。
需要注意的是,如果使用单元测试,那么单元测试target也必须使用上文所说的Coverage编译配置项,因为运行单元测试时,会自动编译主target的同名编译配置项。这个开源工具是通过run_code_coverage_post.sh来在test执行完毕之后来启动覆盖率数据收集的,我修改了一下这个脚本,打开一个终端窗口来打印执行过程:
#!/bin/bash
button=`/usr/bin/osascript <<EOT
tell application "Finder"
activate
set dialogText to "Generate code coverage report?"
set cancelText to "Cancel"
set okText to "OK"
set myReply to button returned of (display dialog dialogText buttons
{cancelText, okText} cancel button cancelText default button okText)
end tell
EOT`
if [[ $button = "OK" ]]; then
`/usr/bin/osascript <<EOT
tell application "Terminal"
close back window
do script "/bin/bash ${SRCROOT}/XcodeCoverage/getcov"
end tell
EOT`
fi
echo "Done.”
代码覆盖率的结果,可以用来指导开发者进行充分的调试,或是评估单元测试的case是否足够;第一次完成上面的配置之后,以后的使用是很方便的。
另外需要指出的几点:
1)__gcov_flush在一次测试中是可以被反复调用的,可以边测试边看覆盖率;
2)本文对XcodeCoverage所做的几处修改,在这里可以找到;
3)另外每次覆盖率测试最好用一个全新的build,因此需要将上次build的中间文件全部删除,可以打开Xcode的Product菜单,按住Option键,点击Clear Build Folder…。
xcode进行代码覆盖率测试的更多相关文章
- iOS代码覆盖率测试工具
基于lcov-1.11的:CodeCoverage4iOS 阅读目录 环境准备 Xcode工程配置 构建并安装程序 收集代码覆盖率 过滤结果 合并多个Coverage.info⽂件⽣成覆盖率报告: ...
- Xcode真机测试could not find developer disk image解决方法
原文地址:http://my.oschina.net/u/2340880/blog/521700 Xcode真机测试could not find developer disk image解决方法 在使 ...
- WWDC15 Session笔记 - Xcode 7 UI 测试初窥
https://onevcat.com/2015/09/ui-testing/ WWDC15 Session笔记 - Xcode 7 UI 测试初窥 Unit Test 在 iOS 开发中已经有足够多 ...
- Xcode 真机测试破解方法(转加修改)xcode 4.3 通过
Xcode 真机测试破解方法(转加修改)xcode 4.3 通过 生成本机证书 应用程序->实用工具->钥匙串访问 菜单:钥匙串访问->证书助理->创建证书, 然后按以下图片顺 ...
- VS2015+NUnit+OpenCover 完成单元测试代码覆盖率测试
1.VS2015+NUnit+OpenCover 完成单元测试代码覆盖率测试 https://download.csdn.net/download/qq_39441918/10522539 2.*注意 ...
- Spring Boot 代码覆盖率测试
代码覆盖率测试是规范软件开发流程里一个必不可少的环节.一般都是在PG末尾阶段,伴随着IT自测产生. ↑以上,是自己yy出来的啊,反正我司是这样要求的.不跑覆盖率,鬼知道你在代码里夹杂了一些什么东西. ...
- 使用Cobertura做代码覆盖率测试
经验总结:首先要把cobertura.jar包含ant的classpath路径中,其次要求它包含在测试用例的classpath中: 使用cobertura做代码覆盖率测试中出现的问题:覆盖率始终为0, ...
- 解决Xcode真机测试时ineligible devices的问题
升级了Xcode到6.3,连接真机测试时,出现不能选择设备.如图: 设备系统版本是8.3的,Xcode连接其他低系统版本的设备做真机测试时就不会有这个问题. 有人说这是Xcode6.3的bug. 我的 ...
- Xcode真机测试could not find developer disk image解决方法(支持iOS9.2)
这个问题开发者经常碰到,因为当我们更新手机iOS版本的时候,可能我们开发人员因为项目的需要等原因并一定愿意更新xcode到最新版本.但是老版本的xcode极有可能不支持最新的iOS版本,也有一些旧的i ...
随机推荐
- Fragment加载方式与数据通信
一.加载方式 1. 静态加载 1.1 加载步骤 (1) 创建fragment:创建自定义Fragment类继承自Fragment类,同时将自定义Fragment类与Fragment视图绑定(将layo ...
- 第一篇:操纵MySQL数据库(1) - 基于MySQLdb库
前言 本文讲解在Python语言中使用MySQLdb库操纵MySQL数据库的方法. 准备工作 1. 安装Python和MySQL2. 安装MySQLdb (exe下载地址:http://sourcef ...
- yyb要填的各种总结的坑
已经写好啦的 莫比乌斯反演 杜教筛 动态点分治 斜率优化 Splay 莫队 凸包 旋转卡壳 Manacher算法 Trie树 AC自动机 高斯消元 KMP算法 SA后缀数组 SAM后缀自动机 回文树 ...
- 【CJOJ2512】gcd之和(莫比乌斯反演)
[CJOJ2512]gcd之和(莫比乌斯反演) 题面 给定\(n,m(n,m<=10^7)\) 求 \[\sum_{i=1}^n\sum_{j=1}^mgcd(i,j)\] 题解 首先把公因数直 ...
- 【BZOJ2816】【ZJOI2012】网络(Link-Cut Tree)
[BZOJ2816][ZJOI2012]网络(Link-Cut Tree) 题面 题目描述 有一个无向图G,每个点有个权值,每条边有一个颜色.这个无向图满足以下两个条件: 对于任意节点连出去的边中,相 ...
- LAMP基础
前言:上一篇博文,说到了URL.http的协议.事务以及私有https的实现.此次 一. 概念: LAMP: a:apache m:mariadb,mysql p:php,perl,python 二. ...
- docker 使用案例:部署nginx
首先安装docker.可以参考这篇教程: http://www.runoob.com/docker/windows-docker-install.html 本教程以windows10+ubuntu:1 ...
- windows下的react-native 开发环境搭建
本教程用安卓手机作为演示. 首先安装jdk.本教程基于jdk1.8,安装时有一点要特别注意:jdk和jre必须装到不同目录下,否则初始化react-native项目时大概率报tools.jar not ...
- 深入理解Java虚拟机类加载机制
1.类加载时机 对于类加载的第一个阶段---加载,虚拟机没有强制的约束,但是对于初始化阶段,虚拟机强制规定有且只有以下的5中情况必须开始初始化,当然,加载.验证.准备阶段在初始化前就已经开始. ①使用 ...
- python 中的 args,*args,**kwargs的区别
一.*args的使用方法 *args 用来将参数打包成tuple给函数体调用 例子一:def function(*args): print(args, type(args))function ...