什么是代码覆盖率
代码覆盖率,是一种通过计算测试过程中被执行的源代码占全部源代码的比例,进而间接度量软件质量的方法。它在保证测试质量的时候潜在保证实际产品的质量,可以基于此在程序中寻找没有被测试用例测试过的地方,进一步创建新的测试用例来增加覆盖率。按性质,它属于白盒测试的范畴,即主要依据源代码的内部结构来设计测试用例,通过设计不同的输入来测试软件的不同部分。常见的编程语言,如C/C++,python和Java等,都有相应的代码覆盖率测试工具。
本篇是入门篇,带大家入门代码覆盖率,全量代码覆盖率,关于原理、增加代码进行代码覆盖率后面会一一分享
操作步骤
第一步
创建一个demo,名为CodeCoverageRate01
最终目录如下
第二步
添加编译配置,用于生成覆盖率.profraw文件
第三步
确认覆盖率的范围,因为是demo这里是 all targets
第四步
4.1 添加一个 InstrProfiling.h 文件 引进llvm api
因为我的demo是swift项目会提示添加桥接文件,这里不赘述操作过程
swift
#ifndef InstrProfiling_h
#define InstrProfiling_h
#ifndef PROFILE_INSTRPROFILING_H_
#define PROFILE_INSTRPROFILING_H_
int __llvm_profile_runtime = 0;
void __llvm_profile_initialize_file(void);
const char *__llvm_profile_get_filename();
void __llvm_profile_set_filename(const char *);
int __llvm_profile_write_file();
int __llvm_profile_register_write_file_atexit(void);
const char *__llvm_profile_get_path_prefix();
#endif /* PROFILE_INSTRPROFILING_H_ */
#endif /* InstrProfiling_h */
4.2 添加CodeCoverageTool类提供API
js
import Foundation
import UIKit
private let instance:CodeCoverageTool = CodeCoverageTool()
@objc public class CodeCoverageTool:NSObject {
var isRegister:Bool = false
public static func shared() -> CodeCoverageTool {
return instance
}
//注册
func registerCoverage(moduleName: String) {
if isRegister {
return
}
isRegister = true
NotificationCenter.default.addObserver(self,
selector: #selector(didEnterBackgroudNotification),
name: UIApplication.didEnterBackgroundNotification,
object: nil)
let name = "\(moduleName).profraw"
print("registerCoverage, moduleName: \(moduleName)")
let fileManager = FileManager.default
do {
let documentDirectory = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)
let filePath: NSString = documentDirectory.appendingPathComponent(name).path as NSString
print("registerCoverage filePath: \(filePath)")
__llvm_profile_set_filename(filePath.utf8String)
} catch {
print(error)
}
}
//合适的时机代码覆盖率上报
func saveAndUpload() {
__llvm_profile_write_file()
}
@objc private func didEnterBackgroudNotification() {
self.saveAndUpload()
}
}
4.3 添加测试 TestSwift.swift
js
import Foundation
class TestSwift {
public func test() {
print("hello, i`m swift class")
}
public func test11() {
print("hello, i`m test11")
}
}
TestObjc
js
#import "TestObjc.h"
@implementation TestObjc
- (void)test {
NSLog(@"hello , i`m objc class");
}
- (void)test11 {
NSLog(@"hello , i`m test11");
}
@end
在ViewController.swift里调用
js
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
test()
}
@objc private func test() {
TestObjc().test()
TestSwift().test()
}
}
第五步
业务使用
js
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
CodeCoverageTool.shared().registerCoverage(moduleName: "testCodeCoverage")
return true
}
运行APP,随便操作几下,退到后台
第六步
捞取.profraw文件 步骤 xcode -> windows -> devices and simulators
下载后,点击查看包内容,如下可以拿到.profraw文件
第七步
合成.testCodeCoverage.profdata
首先把.profraw和对应的二进制文件放在一个文件夹里,如下
执行如下指令
js
xcrun llvm-profdata merge -sparse testCodeCoverage.profraw -o testCodeCoverage.profdata
生成.profdata文件
第八步
生成报告
执行如下指令
js
xcrun llvm-cov show [二进制文件路径] --instr-profile=testCodeCoverage.profdata --format=html -use-color --output-dir ./coverage_report
[二进制文件路径]我的为 /Users/gegaozhao/Library/Developer/Xcode/DerivedData/CodeCoverageRate01-ahzrkhfjrajjnjaolknrsjgxmabw/Build/Products/Debug-iphoneos/CodeCoverageRate01.app/CodeCoverageRate01
效果
点击index.html,跳转到浏览器
到这里流程就讲完了,感谢阅读!