测试 pytest 插件时如何获取覆盖率报告?

How to get coverage reporting when testing a pytest plugin?

上下文

我正在更新一个测试覆盖率很低的继承存储库。 repo 本身是一个 pytest 插件。我已经将回购更改为使用 toxpytest-cov,并将“原始”测试转换为使用 pytester,如测试插件时 pytest 文档中所建议的那样。

测试和 tox 构建等非常有效。但是,覆盖率报告了 class 定义、导入等错误的缺失。这是因为代码本身是作为 pytest 实例化的一部分导入的,并且在测试实际开始之前不会被“覆盖” .

我已经阅读了 pytest 文档、pytest-cov 和 coverage 文档以及 tox 文档,并尝试了几种配置,但无济于事。我已经用尽了 google 个关键字组合,这些组合可能会让我找到一个好的解决方案。

存储库布局

pkg_root/
    .tox/
        py3/
            lib/
                python3.7/
                    site-pacakges/
                        plugin_module/
                            supporting_module.py
                            plugin.py
                            some_data.dat
    plugin_module/
        supporting_module.py
        plugin.py
        some_data.dat
    tests/
        conftest.py
        test_my_plugin.py
    tox.ini
    setup.py
    

一些带有评论的相关片段:

tox.ini

[pytest]
addopts = --cov={envsitepackagesdir}/plugin_module --cov-report=html
testpaths = tests

这个配置给我一个没有收集到数据的错误;在这种情况下没有创建 htmlcov。

如果我只使用 --cov,我会得到(预期的)非常嘈杂的覆盖范围,它显示了功能命中和未命中,但上面报告了导入、class 定义等的错误未命中.

conftest.py

pytest_plugins = ['pytester']  # Entire contents of file!

test_my_plugin.py

def test_a_thing(testdir):
    testdir.makepyfile(
        """
            def test_that_fixture(my_fixture):
                assert my_fixture.foo == 'bar'
        """
    )
    result = testdir.runpytest()
    result.assert_outcomes(passed=1)

如何获得准确的报告?有没有办法推迟插件加载,直到 pytester 测试需要它?

不使用 pytest-cov 插件,而是使用 运行 pytest 的覆盖率:

coverage run -m pytest ....

这样,覆盖将在 pytest 之前开始。

不用pytest-cov也能达到你想要的效果。


❯ coverage run --source=<package> --module pytest --verbose <test-files-dirs> && coverage report --show-missing
或更短
❯ coverage run --source=<package> -m pytest -v <test-files-dirs> && coverage report -m
示例:(针对您的目录结构)
❯ coverage run --source=plugin_module -m pytest -v tests && coverage report -m
======================= test session starts ========================
platform darwin -- Python 3.9.4, pytest-6.2.4, py-1.10.0, pluggy-0.13.1 -- /Users/johndoe/.local/share/virtualenvs/plugin_module--WYTJL20/bin/python
cachedir: .pytest_cache
rootdir: /Users/johndoe/projects/plugin_module, configfile: pytest.ini
collected 1 items

tests/test_my_plugin.py::test_my_plugin PASSED               [100%]

======================== 1 passed in 0.04s =========================
Name                            Stmts   Miss  Cover   Missing
-------------------------------------------------------------
plugin_module/supporting_module.py  4      0   100%
plugin_module/plugin.py             6      0   100%
-------------------------------------------------------------
TOTAL                              21      0   100%

为了获得更好的输出,您可以使用:

❯ coverage html && open htmlcov/index.html


文档

❯ coverage -h
❯ pytest -h

coverage

run -- Run a Python program and measure code execution.

-m, --module --- Show line numbers of statements in each module that weren't executed.

--source=SRC1,SRC2, --- A list of packages or directories of code to be measured.

report -- 报告模块的覆盖率统计信息。

-m, --show-missing --- Show line numbers of statements in each module that weren't executed.

html -- 创建一个 HTML 报告。

pytest

-v, --verbose -- increase verbosity.