- 首发:2023-05-25 17:13:13
- 教程
- 1068
测试覆盖率是衡量软件测试质量的一个重要指标,它表示在运行测试用例时,被执行到的代码占总代码数的百分比。通过测试覆盖率,我们可以评估测试集对源码的覆盖程度及潜在漏洞。
本文将介绍两种使用LLVM实现C++测试覆盖率的方法:
- 方案1 使用lcov和llvm-cov将gcda文件转换为lcov.info文件。
- 方案2 使用grcov。
方案1:使用lcov和llvm-cov实现gcda -> gcov -> lcov.info
1. 环境准备
首先,确保已安装LLVM、Clang、lcov以及其相关工具。
各平台安装方法参考https://github.com/yi-ge/cpp-practice。
其中Windows平台安装lcov:
choco install lcov
然后执行lcov命令的时候需要手动使用perf
执行安装目录下bin/lcov
程序。
也可以在WSL2
或者其他可以执行Shell脚本的类 Unix 终端(例如Git Bash、Cygwin等)安装lcov
。
2. 编译代码与生成.gcda文件
在这里,我们提供两种方法来生成.gcda文件:
方法一:
使用以下命令启用覆盖率信息收集,并编译你的C++项目:
clang++ -fprofile-instr-generate -fcoverage-mapping -o your_program your_source.cpp
其中-fprofile-instr-generate
和-fcoverage-mapping
选项用于激活覆盖率信息收集。
方法二:
在CMakeLists.txt文件中添加coverage相关参数(LLVM 8+),例如:
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -fno-inline -O0 -fprofile-arcs -ftest-coverage")
接下来按照普通流程编译和运行项目即可生成对应的.gcda文件。
3. 执行程序
接下来,运行编译好的可执行文件:
./your_program
运行完毕后,会在当前目录下生成.profraw
文件(方法一),或 .gcda
文件(方法二)。该文件记录了覆盖率原始数据。
4. 转换.profraw文件为.gcda文件(仅方法一)
如果使用方法一,请使用llvm-profdata
工具将.profraw
文件转换为.gcda
格式:
llvm-profdata merge -sparse default.profraw -o your_program.gcda
5. 使用llvm-cov生成.gcov文件
通过llvm-cov gcov
命令将.gcda
文件转换为.gcov
文件:
llvm-cov gcov -f -b your_source.gcda
6. 使用lcov生成lcov.info文件
现在我们已经得到了.gcov文件,接下来可以用lcov合并覆盖率数据并生成lcov.info
文件:
lcov --capture --directory . --output-file lcov.info
由于在基于llvm的项目中依次执行llvm-cov gcov
很麻烦,除了递归脚本外,还推荐另外一种方法,具体实现方案如下:
llvm-gcov.sh文件:
#!/bin/bash
uNames=$(uname -s)
osName=${uNames:0:4}
if [ "$osName" == "Darw" ]; then # Darwin
exec llvm-cov gcov "$@"
elif [ "$osName" == "Linu" ]; then # Linux
exec llvm-cov-16 gcov "$@"
elif [ "$osName" == "MING" ]; then # MINGW, windows, git-bash
exec llvm-cov-16 gcov "$@"
fi
llvm-gcov.bat文件:
@echo off
:DetectOS
if "%OS%" == "Windows_NT" (
set "osName=Win"
) else (
echo Unsupported platform: %OS%
exit /b 1
)
:RunLLVMCov
if "%osName%" == "Win" (
llvm-cov gcov %*
) else (
echo Unsupported platform: %osName%
exit /b 1
)
创建名为scripts的文件夹,并将提供的llvm-gcov.sh (macOS, Linux)或llvm-gcov.bat (Windows) 文件放入其中。这些脚本用于在不同平台上调用正确的llvm-cov工具。
参考以下bash脚本生成覆盖率测试文件lcov.info:
#!/bin/bash
# 使用bash shell执行此脚本
COVERAGE_FOLDER=coverage
COVERAGE_FILE=lcov.info
REPORT_FOLDER=report
# 删除已存在的覆盖率文件夹,然后创建一个新的覆盖率文件夹
rm -rf ${COVERAGE_FOLDER}
mkdir ${COVERAGE_FOLDER}
# 获取操作系统名称并截取前四个字符
uNames=$(uname -s)
osName=${uNames:0:4}
# 删除与当前单元测试无关的.gcda文件
# find build -name "*.gcda" -not -path "*flip_columns_for_maximum_number_of_equal_rows*" -exec rm {} \;
# 设置临时覆盖率文件路径
TMP_COVERAGE_FILE=${COVERAGE_FOLDER}/${COVERAGE_FILE}_tmp
# 根据操作系统类型执行相应的lcov命令
if [ "$osName" == "Darw" ]; then # Darwin
echo "Mac"
lcov --gcov-tool $PWD/scripts/llvm-gcov.sh --rc lcov_branch_coverage=1 -c -d build -o ${TMP_COVERAGE_FILE}
elif [ "$osName" == "Linu" ]; then # Linux
echo "Linux"
lcov --gcov-tool $PWD/scripts/llvm-gcov.sh --rc lcov_branch_coverage=1 -c -d build -o ${TMP_COVERAGE_FILE}
elif [ "$osName" == "MING" ]; then # MINGW, windows, git-bash
echo "Windows"
lcov --gcov-tool $PWD/scripts/llvm-gcov.sh --rc lcov_branch_coverage=1 -c -d build -o ${TMP_COVERAGE_FILE}
fi
# 从临时覆盖率文件中移除包含目录
echo "从临时覆盖率文件中移除包含目录"
lcov --remove ${TMP_COVERAGE_FILE} -o ${TMP_COVERAGE_FILE} "*/include/*"
# 从临时覆盖率文件中提取src目录下的覆盖率数据,并保存到最终的覆盖率文件
lcov --rc lcov_branch_coverage=1 -e ${TMP_COVERAGE_FILE} "*src*" -o ${COVERAGE_FOLDER}/${COVERAGE_FILE}
# 生成覆盖率报告(注释掉,如需启用,请取消注释)
# genhtml --rc genhtml_branch_coverage=1 ${COVERAGE_FOLDER}/${COVERAGE_FILE} -o ${COVERAGE_FOLDER}/${REPORT_FOLDER}
在当前目录下执行此脚本,生成覆盖率测试文件lcov.info
。
7. 生成可视化报告
使用genhtml
命令将lcov.info
转换为HTML格式:
genhtml -o coverage_report --branch-coverage lcov.info
这将在coverage_report
目录下生成一个包含覆盖率详细信息的HTML报告。通过浏览器打开index.html
来查看报告。
方案2:使用grcov实现C++测试覆盖率
grcov是一个用Rust编写的覆盖率收集工具,可以直接分析.gcda
文件并生成覆盖率报告。
首先安装grcov。
如果已经配置好Rust环境以及对应的cargo工具:
cargo install grcov
否则可以直接从github仓库下载编译好的二进制文件,可以参考跨平台自动下载及安装脚本https://github.com/yi-ge/cpp-practice/blob/main/scripts/grcovDownloader.cpp。
然后使用以下命令运行测试并生成覆盖率报告:
LLVM_PROFILE_FILE="your_program-%p-%m.profraw" ./your_program
grcov . --binary-path ./ --source-dir . --output-path cover/lcov.info --output-type lcov
这将生成一个名为lcov.info
的文件,其中包含覆盖率数据。同样,你可以使用直接生成HTML可视化报告:
grcov . --binary-path ./ --source-dir . --output-path coverage/ --output-type html
总结
如上所述,在方案1中我们可以使用lcov和llvm-cov工具链生成覆盖率报告,或者通过添加coverage flags在CMakeLists.txt中直接生成.gcda文件。在方案2中,我们可以使用grcov直接分析.gcda文件并生成覆盖率报告。这两种方法都可以满足不同的需求,方案1更适用于熟悉lcov工具链的开发者,而方案2对于喜欢尝试新工具的开发者来说是一个很好的选择。
无论采用哪种方案,测试覆盖率是提高软件质量、降低潜在风险的关键指标,因此建议在项目开发过程中充分利用这些工具和方法,确保代码的健壮性和可靠性。
另外,grcov的优点是跨平台更方便。尤其是对于Windows平台,在不考虑wsl或者类Unix终端的情况下,安装perf来直接运行lcov程序非常容易出现问题。因此,更推荐使用方案2。
暂无内容




谢谢,你写的最详细,也很有效的解决了撕裂问题
很棒的教程,比我之前配置ap的方式更优雅
这个问题应该是修改没有成功,可能与系统版本更新有关系。
没错,用批处理解决是非常合适的!
请在阿里云文档里面查找相应错误码