如何为被测子进程生成代码覆盖率报告?
解决子进程代码覆盖率统计问题
场景回顾
我们有目标程序thingy.py:
# thingy.py import sys print("ready") for line in sys.stdin: print(line, end='')
以及对应的端到端测试test_thingy.py,通过subprocess启动真实进程进行测试:
# test_thingy.py import pytest import subprocess import sys @pytest.fixture def thingy_instance(): proc = subprocess.Popen( [sys.executable, "-um", "thingy"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding="utf-8") for line in proc.stdout: if "ready" in line: break yield proc proc.terminate() proc.wait() def test_thingy(thingy_instance): stdout, stderr = thingy_instance.communicate("Hello!") assert stdout == "Hello!"
执行coverage run --source . -m pytest后,thingy.py的覆盖率始终为0%,但直接运行coverage run -m thingy却能正常统计。这是因为Coverage默认只追踪主进程,不会自动监控子进程的代码执行。
可行解决方案
方案1:子进程主动启动Coverage并合并报告
修改测试代码中的subprocess.Popen命令,让子进程通过Coverage启动,指定独立的覆盖率数据文件,最后合并所有数据:
- 更新测试用例中的子进程启动命令:
proc = subprocess.Popen( [sys.executable, "-m", "coverage", "run", "--source", ".", "--data-file", ".coverage.subprocess", "-m", "thingy"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding="utf-8" )
- 执行测试后合并数据并生成报告:
coverage combine coverage report
方案2:使用并行模式自动处理多进程数据
利用Coverage的--parallel-mode自动生成带标识的覆盖率文件,后续合并即可:
- 启动测试时启用并行模式:
coverage run --parallel-mode --source . -m pytest
- 修改子进程启动命令,同样启用并行模式:
proc = subprocess.Popen( [sys.executable, "-m", "coverage", "run", "--parallel-mode", "--source", ".", "-m", "thingy"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, encoding="utf-8" )
- 合并数据并生成报告:
coverage combine coverage report
方案3:通过启动钩子自动追踪子进程(推荐)
无需修改测试代码,通过环境变量和启动钩子让所有子进程自动被Coverage监控:
- 创建
.coveragerc配置文件:
[run] source = . parallel = True
- 创建
sitecustomize.py文件(放在项目根目录):
import coverage coverage.process_startup()
- 设置环境变量并执行测试:
export COVERAGE_PROCESS_START=$(pwd)/.coveragerc coverage run --source . -m pytest coverage combine coverage report
这个方案下,所有由主进程启动的Python子进程都会自动加入覆盖率统计,适合复杂的多进程测试场景。
核心原理
Coverage默认仅追踪启动它的主进程,子进程是独立的Python解释器实例,不会继承主进程的监控状态。上述方案要么让子进程主动启动Coverage生成独立数据文件,要么通过钩子机制让子进程自动触发Coverage统计,最后通过coverage combine合并所有进程的覆盖率数据,得到完整报告。
内容的提问来源于stack exchange,提问作者Marcus Harrison
相关产品推荐
相关产品推荐

