在传统覆盖率收集方案中,C++ 编译时,添加覆盖率参数 -fprofile-arcs -ftest-coverage。 编译后能生成 gcno 文件。 在执行机上执行进程和测试脚本后,退出进程时,获取到覆盖率执行文件 gcda。通过 lcov 工具根据 源码、gcda、gcno 文件生成覆盖率数据。再使用 genhtml 生成覆盖率报告。
传统方案中的问题:
- 需要修改 makefile 或者 cmake 文件;
- 需要停止进程才能获取到覆盖率;
- 对于源码不同 commit id 的覆盖率数据无法累加;
- 无法获取到相对于 master 到增量覆盖率。
希望通过非入侵到方式,在不停服到情况下自动获取到覆盖率。
通过工具脚本、计算服务等,将整个覆盖率获取流程自动化。另一方面,解决了传统方案中遇到的问题。
- 在编译前使用插桩脚本对源码插桩。编译完成后,通过脚本将 gcno 文件上传至cos;
- 在执行机上启动服务,定时获取覆盖率文件 gcda 上传至 cos,并触发覆盖率任务,将任务信息放入 kafka;
- 覆盖率计算服务(可多台部署)通过获取 kafka 中任务,并从 git拉取源码,从 cos 拉取源数据进行覆盖率计算、累加等,最后生成覆盖率结果写入数据库,覆盖率报告上传至cos;
- 通过 API 获取到指定 commit id 的覆盖率数据以及报告的 cos 地址
./script/instrumentation.py 覆盖率插桩脚本
./CreaTask 创建覆盖率任务API
./GetCover 获取覆盖率结果API
./DoTask 覆盖率计算服务
1、 如何实现不停服?
通过在入口函数(比如 main)添加信号量捕获方法 signal(),当获取到指定信号量时,调用 __gcov_flush() 刷新本地 gcda 文件。
2、 如何累加覆盖率数据?
a. 如果之前的覆盖率数据与当前覆盖率数据对于源码到 commit id 相同,则通过 lcov 命令直接整合; b. 如果 commit id 不同,则根据 git diff 的变更,通过计算将前一次覆盖率数据映射到当前结果中。
3、 如果计算增量覆盖率?
通过 git diff 计算出所有增量代码,再通过覆盖率数据标记增量代码中的覆盖情况。