iOS Gcov 探测测试代码覆盖率
1. Xcode工程设置
首先配置Xcode工程,生成对应的coverage文件(GCNO文件)
instrument program flow : yes
generate legacy test coverage files : yes
2.真机运行设置
为了能够在真机上把文件取出来,需要配置plist打开文件共享
application supportsitunesfiles sharing=yes
3.代码修改
3.1 设置目标属性
首先要设置GCDA文件保存的位置:
NSString *covFilePath = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/coverage_files"];
setenv("GCOV_PREFIX", [covFilePath cStringUsingEncoding: NSUTF8StringEncoding], 1);
setenv("GCOV_PREFIX_STRIP", "1", 1);
这里通过设置环境变量GCOV_PREFIX设置路径。而GCOV_PREFIX_STRIP设置源文件绝对路径中去掉多少级别。比如设置为1的话直接去掉了Users目录:
CHANGZENG-MC0:tmp apollo$ tree coverage_files/
coverage_files/
└── apollo
└── Library
└── Developer
└── Xcode
└── DerivedData
└── TestGCOV-cxksfhbrmyzmdgbbxfollivoxxry
└── Build
└── Intermediates
└── TestGCOV.build
└── Debug-iphoneos
└── TestGCOV.build
└── Objects-normal
└── arm64
├── AppDelegate.gcda
├── ViewController.gcda
└── main.gcda
13 directories, 3 files
CHANGZENG-MC0:tmp apollo$ pwd
/Users/apollo/Desktop/tmp
3.2 生成文件
要生成.gcda文件,还需要在执行测试代码的最后调用
void __gcov_flush(void);
该函数是个内置函数,在系统库中,所以只要extern一下就可以调用:
extern "C" void __gcov_flush(void);
比如代码:
extern "C" void __gcov_flush(void);
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self testIfEles];
__gcov_flush();
}
- (void) testIfEles {
int con = 1;
int num = 0;
if (con) {
num ++;
} else {
num --;
}
NSLog(@"num is %d", num);
}
会生成GCDA文件:
AppDelegate.gcda ViewController.gcda main.gcda
4. 取出GCNO文件 和GCDA文件
4.1 GNCO
GCNO文件是在编译期间生成的类似符号表的文件,在Xcode的Product里面可以找到构建时候的目录,在这个目录中如下的路径:
/Users/apollo/Library/Developer/Xcode/DerivedData/TestGCOV-cxksfhbrmyzmdgbbxfollivoxxry/Build
路径中找到:
Intermediates/TestGCOV.build/Debug-iphoneos/TestGCOV.build/Objects-normal/
下面的arm64或者386等架构平台下找到GCNO文件:
CHANGZENG-MC0:arm64 apollo$ ls *.gcno
AppDelegate.gcno ViewController.gcno main.gcno
4.2 GCDA
如果是模拟器运行,上面的covFilePath
就是对应的路径位置,直接打开即可。如:
CHANGZENG-MC0:Documents apollo$ pwd
/Users/apollo/Library/Developer/CoreSimulator/Devices/DE6523B3-1718-4541-B156-23819BFE49DC/data/Containers/Data/Application/03A33ECA-4D66-4C4A-8796-9E78E107305C/Documents
CHANGZENG-MC0:Documents apollo$ ls
coverage_files
CHANGZENG-MC0:Documents apollo$ ls coverage_files/
AppDelegate.gcda ViewController.gcda main.gcda
如果是真机,通过上面的plist设置,可以打开iTunes。然后在设备的APP里面看到有共享文件的App:
将文件导出来,就可以得到GCDA文件。
5.采用LCOV分析
5.1 lcov
安装lcov:
在 http://ltp.sourceforge.net/coverage/lcov.php下载lcov文件。比如Mac下,把目录解压后,把bin目录加入到bash_profile中:
## lcov
export PATH=$PATH:/Users/apollo/Software/lcov-1.13/bin
5.2 生成html文件
将上面的GCNO和GCDA文件copy到同一个目录下,然后执行:
lcov -c -d . -o TestGCOV.info
这里-d指定就是上面文件所在位置。 -o表示输出文件:
CHANGZENG-MC0:gfile apollo$ lcov -c -d . -o TestGCOV.info
Capturing coverage data from .
Found LLVM gcov version 8.1.0, which emulates gcov version 4.2.0
Scanning . for .gcda files ...
Found 3 data files in .
Processing AppDelegate.gcda
Processing main.gcda
Processing ViewController.gcda
然后在使用命令 genhtml生成html文件:
CHANGZENG-MC0:gfile apollo$ genhtml -o html TestGCOV.info
Reading data file TestGCOV.info
Found 4 entries.
Found common filename prefix "/Users/apollo/Work/Repos/tc-svn.tencent.com/GcloudServices_proj/trunk/gcloud_voice/gcov/iOS/TestGCOV"
Writing .css and .png files.
Generating output.
Processing file TestGCOV/AppDelegate.h
Processing file TestGCOV/main.m
Processing file TestGCOV/ViewController.m
Processing file TestGCOV/AppDelegate.m
Writing directory view page.
Overall coverage rate:
lines......: 69.0% (20 of 29 lines)
functions..: 46.2% (6 of 13 functions)
在输出目录-o表示的html文件夹中,用浏览器打开index.html文件:
可以看到覆盖率