16

Context

I am updating an inherited repository which has poor test coverage. The repo itself is a pytest plugin. I've changed the repo to use tox along with pytest-cov, and converted the "raw" tests to use pytester as suggested in the pytest documentation when testing plugins.

The testing and tox build, etc. works great. However, the coverage is reporting false misses with things like class definitions, imports, etc. This is because the code itself is being imported as part of pytest instantiation, and isn't getting "covered" until the testing actually starts.

I've read pytest docs, pytest-cov and coverage docs, and tox docs, and tried several configurations, but to no avail. I've exhausted my pool of google keyword combinations that might lead me to a good solution.

Repository layout

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
    

Some relevant snippets with commentary:

tox.ini

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

This configuration gives me an error that no data was collected; no htmlcov is created in this case.

If I just use --cov, I get (expected) very noisy coverage, which shows the functional hits and misses, but with the false misses reported above for imports, class definitions, etc.

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)

How can I get an accurate report? Is there a way to defer the plugin loading until it's demanded by the pytester tests?

4

2 回答 2

26

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

coverage run -m pytest ....

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

于 2020-06-05T21:40:28.400 回答
10

您可以在没有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

覆盖率 HTML 报告


文档

❯ coverage -h
❯ pytest -h

coverage

run-- 运行 Python 程序并测量代码执行情况。

-m, --module--- 显示每个模块中未执行的语句的行号。

--source=SRC1,SRC2,--- 要测量的代码包或目录的列表。

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

-m, --show-missing--- 显示每个模块中未执行的语句的行号。

html-- 创建一个 HTML 报告。

pytest

-v, --verbose——增加冗长。

于 2021-06-15T14:13:18.557 回答