If you cannot measure it, you cannot improve it.
在持续集成的过程中,需要高覆盖率的自动化测试。这篇文章说一说如何计量覆盖率,以及靶向提升。
用到的工具:
问题一:总共有多少代码被覆盖?
- 执行测试 【可能有多条语句】;
coverage run -m unittest discover tests
coverage run -a -m behave --lang zh-CN # 当有多种测试框架 or 语句时,用 -a 附加覆盖率
- 报告结果 【有两种输出地方,输出到shell,输出到文件】;
coverage report # 输出到命令行
coverage xml -o coverage-reports/coverage.xml # 以xml文件输出
coverage html # 以html文件输出
coverage report
会把所有测试中覆盖到的文件输出打印到命令行,给出每个文件的覆盖率,以及汇总之后的代码行数和覆盖率。
问题二: 如何提升总体覆盖率?
以HTML输出为例,可以通过点击到每个文件内部,页面中会把未被测试覆盖到的代码用红色block标出, 而已被覆盖的代码会有绿色标识。
当我们知道哪些代码没有被覆盖时?那就写更多的测试覆盖它们就好了。
问题三: 新分支相对于主分支(master),有多少代码未被覆盖,是哪些代码?
解决这个问题可参见diff-cover,思路是:coverage
获得每行代码的覆盖情况 + git diff
获得变更的代码行 => 变更的代码行的覆盖情况。
由于diff-cover完全依赖coverage
和git
,所以在执行之前,请务必保证覆盖率文件(coverage.xml)已经存在了。
diff-cover coverage-reports/coverage.xml # 未明确指定输出文件,则输出到shell
diff-cover coverage-reports/coverage.xml --html-report 123.html # 输出到HTML文件
同coverage
,既可以在命令行看到整体的覆盖率统计,也可以在html文件中查看哪些代码没有被覆盖,更加靶向的提升测试的覆盖率。
尾记
- 覆盖率的集成
在知道了代码的覆盖率之后,可以把它加入到持续集成的pipeline中。可以规定,每次MR的新增代码覆盖率不得低于90%,否则CI失败。
#!/usr/bin/env bash
source ci/config.sh
source ci/dingding.sh
COVERAGE_REPORT_FILE="coverage-reports/coverage.xml"
if [[ ! -e $COVERAGE_REPORT_FILE ]];then
echo "Coverage file does not exit, plz run test first."
exit 1
fi
new_coverage_ratio=$(pipenv run diff-cover $COVERAGE_REPORT_FILE | grep -E 'Coverage:' | sed -e 's/[^0-9]//g')
echo "$new_coverage_ratio"
total_coverage_ratio=$(grep -oE 'line-rate="(1|0\.[0-9]+)"' $COVERAGE_REPORT_FILE | head -1 | grep -oP '[0-9]{2}(?=\d*")' | head -1)
echo "$total_coverage_ratio"
if [[ (-z "$new_coverage_ratio" || $new_coverage_ratio -gt $new_coverage_threshold) && ($total_coverage_ratio -eq 1 || $total_coverage_ratio -ge $total_coverage_threshold) ]]
then
echo "测试覆盖率很好,请继续保持 ~"
exit 0
fi
echo "测试覆盖率不合格,请重新提交 ~"
exit 1
- 代码质量的自动化监控
代码质量,既是一个空空如也的事情,也是一个命脉相关的事情。测试覆盖率只是代码质量中的一环,还有诸如 code smell, 代码复杂度, 重复度等,如果懒得锱铢必较,可以使用成熟的自动化的检测工具,如sonar。加入CI流程,设定规则,保护代码。
- 面向质量编程
覆盖率只是一个显性的指标,如果弄虚作假,完全可以写一个shi一样的测试用例,提高覆盖率,但对于保护代码没有一点帮助。
用各种各样的工具,不是希望身为程序员的我们面向KPI、面向指标、面向覆盖率编程,而是希望注意代码质量,面向自己产出的每一行代码,保质保量,保持身心愉快。