背景描述:
公司需要对测试用例的对工程代码的覆盖率做统计,因此需要用到coverage,这里有个特殊的点,公司的工程运行时要在容器中进行的。
实际应用:
1. 首先,需要下载coverage: pip3 install coverage
2. 然后,由于工程是个django项目,所以需要在根目录创建一个配置文件:.coveragerc 文件。
这里我们简单介绍下这个 .coveragerc 文件:
Coverage 支持很多配置选项,为了方便,通常将这些配置写在名为 .coveragerc
的文件中, Coverage 运行时会从项目根目录读取这个配置文件。
3. 接下来,就是配置这个 .coveragerc 文件。
基本的配置:
[run]
branch = True
source = .[report]
show_missing = False
Coverage 的配置遵循 ini 文件语法。简单来说就是,[section]
代表一个配置块,用于组织相关的一组配置。例如这里 [run]
是一个配置块,[report]
是另一个配置块,两个块下都有相关的一些配置项。
配置项的格式为 key = value
。
这几个简单配置项的含义为:
branch = True
是否统计条件语句的分支覆盖情况。if 条件语句中的判断通常有 True 和 False 两种情况,设置branch = True
后,Coverage 会测量这两种情况是否都被测试到。source = .
指定需统计的源代码目录,这里设置为当前目录(即项目根目录)。show_missing = True
在生成的统计报告中显示未被测试覆盖到的代码行号。
4. 然后就可以运行 coverage run your_test.py 命令了,这里需要注意,如果有多个测试文件,对同一个工程做测试的话,这里最好加上参数 -p ,即:coverage run -p your_test.py 命令,这是因为没运行一个测试,都会生成一个 .coverage文件,为了保证多个测试生成的 .coverage 文件不重名,所以就需要 -p参数。like this:
当然,由于是做统计,所以在有多个测试对同一个工程做覆盖率的场景下,就最好不要弄出很多的这种 .coverage.xxxx文件,我们就需要将多个.coverage.xxxx,进行合并。这时就需要使用命令,coverage combine 命令,注意在ubantu里,如果是用pycharm打开的文件,或者是直接用terminal打开的文件,都是可以看到 .coverage.xxx文件的,但是在容器里是看不到 .coverage.xxx文件的,这里注意,虽然看不到,但不代表它不存在。like this:
这时,我们只需要在容器里执行命令:coverage combine 即可
这样就可以把多个 .coverage.xxx 文件合并为一个文件 .coverage(注意:配置文件后面有 rc )。
5. 最后,就可以查看报告了:
coverage report 即可
这下统计的就是多个测试对同一个工程的总体覆盖率,由于存在同一段代码被多个测试所覆盖的这种场景,所以这个合并后的总覆盖率会小于各个测试覆盖率的和。简单来说,我这里有2个测试,一个总覆盖率是 15% 一个是 8%, 加起来为 23% ,但合并后的总覆盖率却为19%。
ok,到这里,我的任务就完成了。
但是,这里的而局限性很大,而且在后来的代码审视过程中,被发现是有问题的。因为涉及的好多文件的覆盖率是 0%,这不正常。
后来我将 .coveragerc 文件做了些变更:
改为这样:
或者:
结果都是,只有test.py本身和直接被其调用的文件的覆盖率:
这显然是不符合我的预期的。由于我的工程是个web项目,test中经常是通过http访问web服务,来检测服务是否正常,同时通过访问服务返回的数据判断是否符合预期。这样一来,通过目前的方式,就肯定无法统计web服务中有那些文件被访问了,哪些又没test到。
基于,这个问题,最后我找到了解决方法(还是从其他工程的测试命令中倒腾出来的)哎....
在新的方式中, .coveragerc 文件,依旧使用最开始的设置。
然后只需要在工程根目录下执行 coverage 命令就行。
coverage run -p manage.py test test_file_path 即可
其中 -p 参数,上述文中有介绍,用于区分多个测试文件的覆盖率报告
test_file_path 参数是指要跑的测试文件所在的文件夹(该命令会将文件夹中所有的test文件都执行一遍)
其它参数为固定模式无需改动。
看看实际执行:
现在再看,是不是就对了,同时也证明了之前的做法不对,有问题。
另外,在已经有报告的情况下,想转html报告,执行命令:coverage html 即可。
好吧.....我又补充来了......
其实,对coverage最全面的用法,还是得看说明文档。。。。网上基本没有很全的介绍。。。。真的上头啊。。。。今天遇到个要coverage的,目标是在一堆文件中,只需个别文件的覆盖率报告。。。好吧,上面的方法就全部宣布,拜拜了。。。
直接在客户端,输入 coverage --help 查看下命令呗,到底这能干啥,全在这里了:
(py3_10env) ymengkai@ubuntu:~/p4/scm_project/build$ coverage --help
Coverage.py, version 7.1.0 with C extension
Measure, collect, and report on code coverage in Python programs.usage: coverage <command> [options] [args]Commands:annotate Annotate source files with execution information.combine Combine a number of data files.debug Display information about the internals of coverage.pyerase Erase previously collected coverage data.help Get help on using coverage.py.html Create an HTML report.json Create a JSON report of coverage results.lcov Create an LCOV report of coverage results.report Report coverage stats on modules.run Run a Python program and measure code execution.xml Create an XML report of coverage results.Use "coverage help <command>" for detailed help on any command.
Full documentation is at https://coverage.readthedocs.io
再看下,更细致的操作:
(py3_10env) ymengkai@ubuntu:~/p4/scm_project/build$ coverage run --help
Usage: coverage run [options] <pyfile> [program options]Run a Python program, measuring code execution.Options:-a, --append Append coverage data to .coverage, otherwise it startsclean each time.--branch Measure branch coverage in addition to statementcoverage.--concurrency=LIBS Properly measure code using a concurrency library.Valid values are: eventlet, gevent, greenlet,multiprocessing, thread, or a comma-list of them.--context=LABEL The context label to record for this coverage run.--data-file=OUTFILE Write the recorded coverage data to this file.Defaults to '.coverage'. [env: COVERAGE_FILE]--include=PAT1,PAT2,...Include only files whose paths match one of thesepatterns. Accepts shell-style wildcards, which must bequoted.-m, --module <pyfile> is an importable Python module, not a scriptpath, to be run as 'python -m' would run it.--omit=PAT1,PAT2,... Omit files whose paths match one of these patterns.Accepts shell-style wildcards, which must be quoted.-L, --pylib Measure coverage even inside the Python installedlibrary, which isn't done by default.-p, --parallel-mode Append the machine name, process id and random numberto the data file name to simplify collecting data frommany processes.--source=SRC1,SRC2,...A list of directories or importable names of code tomeasure.--timid Use a simpler but slower trace method. Try this if youget seemingly impossible results!--debug=OPTS Debug options, separated by commas. [env:COVERAGE_DEBUG]-h, --help Get help on this command.--rcfile=RCFILE Specify configuration file. By default '.coveragerc','setup.cfg', 'tox.ini', and 'pyproject.toml' aretried. [env: COVERAGE_RCFILE]Full documentation is at https://coverage.readthedocs.io
我了个去,就问,全面不。。。。哎。。。。
看实际应用:
(py3_10env) ymengkai@ubuntu: coverage run -a --include "p4api/p4apiutils.py" ./p4api/tests/p4apiutils_test.py
.....s.............ss........s......s.s.s......
----------------------------------------------------------------------
Ran 47 tests in 186.144sOK (skipped=7)
(py3_10env) ymengkai@ubuntu: coverage report
Name Stmts Miss Cover
-----------------------------------------
p4api/p4apiutils.py 646 214 67%
-----------------------------------------
TOTAL 646 214 67%
(py3_10env) ymengkai@ubuntu: coverage run -a --include "p4api/changespec.py" p4api/tests/changespec_test.py
..................
----------------------------------------------------------------------
Ran 18 tests in 217.033sOK
(py3_10env) ymengkai@ubuntu: coverage report
Name Stmts Miss Cover
-----------------------------------------
p4api/changespec.py 462 55 88%
p4api/p4apiutils.py 646 214 67%
-----------------------------------------
TOTAL 1108 269 76%
哎,看上去,好多了.....
参考文件:统计 Django 项目的测试覆盖率 - 知乎
Configuration reference — Coverage.py 6.3.2 documentation (这是官网,最全面)