pytest-cov icon indicating copy to clipboard operation
pytest-cov copied to clipboard

Set `cov_source` dynamically

Open stefan6419846 opened this issue 3 years ago • 0 comments

Summary

I am currently working on the integration of pytest-cov into a custom pytest plugin. As I want to find files with no coverage as well, I am trying to set cov_source automatically inside my plugin, where I already have a list of all relevant paths.

Is there a way to actually set cov_source dynamically?

Expected vs actual result

Using pytest --cov path/to/my/package --cov-report html will report uncovered files, which is correct.

Trying to set cov_source dynamically from within Python code and running pytest --cov --cov-report html will not report the uncovered files.

Reproducer

Code inside my custom plugin, which is being executed, but has no effect (based upon https://github.com/pytest-dev/pytest-cov/issues/418#issuecomment-657219659):

def pytest_configure(config):
    coverage_plugin = config.pluginmanager.get_plugin('_cov')
    if not coverage_plugin:
        # Coverage is not requested.
        return
    if coverage_plugin.options.no_cov:
        # Coverage has been disabled explicitly.
        return
    if not coverage_plugin.options.cov_source:
        # No coverage parameters passed by user, which means we can inject our own.
        coverage_plugin.options.cov_source = get_directories_for_coverage()

Versions

  • Python 3.6.15
  • pytest 5.4.0
  • pytest-cov 2.1.1
  • coverage 5.3.1

Config

pytest.ini:

[pytest]
python_files=
 */tests/*
python_functions=test*
norecursedirs=
 lib
 lib64
addopts = --disable-warnings

.coveragerc:

[run]
branch = True
omit = 
 */tests/*
 */migrations/*
 bin/*
 lib/*
 lib64/*

[html]
directory = htmlcov

What has been tried to solve the problem

I looked through the source code to find possible alternatives for injecting my code, like using

coverage_plugin.cov_controller.cov.config.source = coverage_plugin.options.cov_source
coverage_plugin.cov_controller.combining_cov.config.source = coverage_plugin.options.cov_source

or adding parameters in pytest_cmdline_main.

Due to pytest_load_initial_conftests inside pytest_cov.plugin where pytest_cov.CovPlugin is initialized and pytest_cov.CovPlugin.__init__ calling pytest_cov.CovPlugin.start, which populates the cov_controller, the modifications I tried seem to fail/seem to have no effect.

The only way I could get this to work is by explicitly "restarting" the plugin after setting the cov_source option:

coverage_plugin.options.cov_source = get_directories_for_coverage()
coverage_plugin.start(controller_cls=coverage_plugin.cov_controller.__class__)

But this approach feels rather hackish and I would prefer a clean solution, as it will show imports etc. as uncovered, which is wrong as well.

stefan6419846 avatar Mar 16 '22 12:03 stefan6419846