Coverage
当我们完成测试用例的编写之后,需要知道测试用例对整个代码的测试覆盖情况。此时可以使用Coverage工具运行测试用例并统计扫描结果。 在Python中,使用Coverage.py作为Coverage工具。Coverage可以执行测试用例,并生成HTML或者XML格式的报告。
安装
在控制台执行python -m coverage
,如果有类似输出:
Code coverage for Python. Use 'coverage help' for help.
说明已经安装过。如果没有安装的话,可以执行:
pip install coverage
就可以完成coverage的安装了。
测试代码和测试用例
待测试代码
code.py
def multiply(x, y):
"""
将2个给定的参数相乘,并返回结果
Args:
:param x: 乘法算子x
:param y: 乘法算子y
Returns:
x * y
"""
if isinstance(x, int):
return x * y
else:
return 0
测试用例代码
test.py
import unittest
from code import multiply
class TestMultiply(unittest.TestCase):
def test_multiply_2_numbers(self):
self.assertEqual(2, multiply(1, 2))
def test_muliply_with_zero(self):
self.assertEqual(0, multiply(1, 0))
def test_multiply_with_char(self):
self.assertEqual(0, multiply("a", 2))
if __name__ == "__main__":
unittest.main()
Coverage的使用
完整的文档请参考: http://coverage.readthedocs.io/en/latest/cmd.html
或者使用help命令查看帮助信息: coverage help
常用的命令有:
coverage run & coverage report
coverage run
命令可以用来执行代码覆盖率统计,只需要通过coverage的run参数执行需要被统计的代码(测试用例)即可。例如:
coverage run test.py arg1 arg2 ..
其中test.py是存放测试用例的文件。arg1, arg2这些是执行test.py需要用到的参数,如果不需要参数可以不传递。
测试用例执行完毕之后会生成一个覆盖率统计结果文件(data file),对应的文件名为
:.coverage
。有了覆盖率统计结果的文件后,只需要再运行report命令,就可以看到统计的结果了,例如执行:coverage report
会得到的结果:
Name Stmts Miss Cover
-----------------------------
code.py 2 0 100%
test.py 16 0 100%
-----------------------------
TOTAL 18 0 100%
其中: Stmts表示语句总数。 Miss表示未执行到的语句数。
覆盖率就等于 (Stmts - Miss)/Stmts
coverage html
使用coverage html
可以得到html格式的测试报告,命令如下:
coverage html -d coveragehtml
生成的报告会直接关联代码,并且支持高亮覆盖和未覆盖的代码,同时也支持排序。-d参数指定的是html文件所在的文件夹。生成的目录类似于:
➜ coveragehtml ls -l
code_py.html
coverage_html.js
index.html
jquery.ba-throttle-debounce.min.js
jquery.hotkeys.js
jquery.isonscreen.js
jquery.min.js
jquery.tablesorter.min.js
keybd_closed.png
keybd_open.png
status.json
style.css
test_py.html
可以在浏览器打开index.html来查看测试覆盖报告。
coverage combine
coverage combine
是一个非常又用的命令,它可以将多份测试覆盖数据文件合并到一个目录里。比如我们的项目中有多个测试用例文件,我们就可以使用该命令将测试覆盖信息放到一个目录里,方便查看整个项目的测试覆盖率情况。
但是,需要注意的是,该命令对目录的结果文件名的格式是有要求的,需要合并的文件必须有同样的前缀,然后后面跟一个名称,然后再跟一个数字(通常是进行号),例如: .coverage.AAA.12345.4566
为了方便将执行结果进行合并,可以在执行统计时,在run参数后面跟一个 -p
参数。它会自动生成符合合并条件的结果文件。例如执行:
coverage run test.py -p
会得到如下结果的一个文件名:
.coverage.seraphln-ubuntu18.23345.830671
coverage run --branch
如果想统计分支覆盖率,可以在run后面添加 --branch
参数。这样的话,在结果时会看到分支覆盖率的统计信息。
➜ coverage report
Name Stmts Miss Branch BrPart Cover
-------------------------------------------
code.py 4 0 2 0 100%
test.py 16 2 2 1 83%
-------------------------------------------
TOTAL 20 2 4 1 88%
其中: Branch表示分支数 BrPart表示未执行到的分支数
coverage run --parallel-mode
如果代码是多进程的,比如一些web程序,想查看被测试代码中子进程的覆盖率,那就需要 --parallel-mode
这个参数。
获取web程序的覆盖率
单元测试
web程序中的单元测试是使用web开发框架提供的client客户端来进行模拟HTTP请求。在Django和Flask中都有client的实现,使用Coverage获取它的测试覆盖率结果跟普通的单元测试的方法是一样的。
E2E test
E2E test是指端到端的测试,是用来模拟用户进行正常操作的测试。常见的e2e测试的流程为:服务端开启一个Web服务,客户端通过HTTP请求来进行测试。
此时想获取端上的覆盖率也可以使用Coverage。这是因为Coverage在实现上使用了atexit模块注册了一个回调函数,在Python退出时将内存中的覆盖率结果写到文件中。被测试脚本只有正常推出或者以 SIGINT 2
信号退出才能触发atexit。才能得到测试覆盖率结果。
注意:
CTRL + C
触发的就是SIGINT 2
信号,所以在e2e test执行完毕之后,使用CTRL + C
就可以得到测试覆盖率文件了。