pytest-cov 如何报告由于 pexpect.spawn 执行的 python 代码的覆盖率?

2023-12-12

我有一个 Python 项目,它使用 pytest-cov 进行单元测试和代码覆盖率测量。

我的项目的目录结构是:

rift-python
+- rift                        # The package under test
|  +- __init__.py
|  +- __main__.py
|  +- cli_listen_handler.py
|  +- cli_session_handler.py
|  +- table.py
|  +- ...lots more...
+- tests                       # The tests 
|  +- test_table.py
|  +- test_sys_2n_l0_l1.py
|  +- ...more...
+- README.md
+- .travis.yml
+- ...

我用Travis来运行pytest --cov=rift tests对于每次签入,我都使用 codecov 查看代码覆盖率结果。

正在测试的包提供了一个命令行界面 (CLI),它从 stdin 读取命令并在 stdout 上生成输出。它开始于python rift.

测试目录包含两种类型的测试。

第一种类型的测试是测试单个类的传统单元测试。例如,测试 test_table.py 导入 table.py,并执行传统的 pytest 测试(使用断言等)。代码覆盖率测量按这些测试的预期工作:codecov 准确报告 rift 包中的哪些行被或不被测试。

# test_table.py (codecov works)

import table

def test_simple_table():
    tab = table.Table()
    tab.add_row(['Animal', 'Legs'])
    tab.add_rows([['Ant', 6]])
    ...
    tab_str = tab.to_string()
    assert (tab_str == "+--------+------+\n"
                       "| Animal | Legs |\n"
                       "+--------+------+\n"
                       "| Ant    | 6    |\n"
                       "+--------+------+\n"
                       ...
                       "+--------+------+\n")

第二种类型的测试使用 pexpect:它使用pexpect.spawn("python rift")启动裂痕包。然后它使用pexpect.sendline将命令注入 CLI (stdin) 并使用pexpect.expect检查 CLI 上命令的输出 (stdout)。测试功能工作正常,但 codecov 没有报告这些测试的代码覆盖率。

# test_sys_2n_l0_l1.py (codecov does not pick up coverage of rift package)
# Greatly simplified example

import pexpect

def test_basic():
    rift = pexpect.spawn("python rift")
    rift.sendline("cli command")
    rift.expect("expected output")  # Throws exception if expected output not seen

问题:如何使用 pexpect 获取代码覆盖率测量结果来报告第二种类型测试的生成的 rift 包中覆盖的行?

注意:我省略了一些我认为不相关的细节,完整的源代码位于https://github.com/brunorijsman/rift-python(更新:此存储库现在包含答案中建议的工作解决方案)


Use coverage run运行 pexpect 程序并收集数据:

如果你经常这样做:

pexpect.spawn("python rift")

然后改为:

pexpect.spawn("coverage run rift.py")

(Source)

测试后,您可能希望将预期结果与“常规”单元测试结果结合起来。coverage.py可以将多个文件合并为一个以进行报告。

创建多个此类文件后,您可以将它们全部复制到一个目录中,然后使用combine命令将它们合并为一个.coverage数据文件:

$ coverage combine

(Source)

测试的另外两个细节:

  • 在此示例的测试程序 (test_sys_2n_l0_l1.py) 中,您必须确保终止 pexpect 生成的时刻与终止测试本身的时刻之间存在延迟。否则,coverage 将没有时间将结果写入 .coverage。我添加了睡眠(1.0)。

  • 使用“coverage run --parallel-mode rift”。需要这样做(a)确保 .coverage 不会被以后的运行覆盖,以及(b)使“覆盖组合”工作(由“pytest --cov”自动运行)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pytest-cov 如何报告由于 pexpect.spawn 执行的 python 代码的覆盖率? 的相关文章

随机推荐