Unable to get missing lines & branches in nose2

938 Views Asked by At

I'm trying to get my tests to report missing lines and branches. I've configured nose2 and coverage to produce line and branch coverage, and as far as I can tell I have set the coverage config correctly to give me the missing lines and branches. However I can't get coverage to give me missing column when run under nose2, but I can if I run it directly.


Consider the following setup in my project directory.

my_module/
    __init__.py
    main.py
tests/
    test_a_thing.py
unittest.cfg
.coveragerc

contents of .coveragerc

[run]
branch = True

[report]
show_missing = True

contents of unittest.cfg

[coverage]
always-on = True
coverage = my_module
coverage-config = .coveragerc

the output of my nose2 command

(example_venv) andy@batman[11:30:53]:/space/test_example$ python -m nose2 -c unittest.cfg --no-user-config
.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
----------- coverage: platform linux, python 3.5.2-final-0 -----------
Name                    Stmts   Miss Branch BrPart  Cover
---------------------------------------------------------
my_module/__init__.py       0      0      0      0   100%
my_module/main.py           4      1      2      1    67%
---------------------------------------------------------
TOTAL                       4      1      2      1    67%

As you can see, it has given me Branch cover, but not told me the missing branches.

If I simply run coverage report (on the produced .coverage file that is left behind after running nose)

(example_venv) andy@batman[11:34:15]:/space/test_example$ coverage report
Name                    Stmts   Miss Branch BrPart  Cover   Missing
-------------------------------------------------------------------
my_module/__init__.py       0      0      0      0   100%
my_module/main.py           4      1      2      1    67%   3, 2->3
-------------------------------------------------------------------
TOTAL                       4      1      2      1    67%

You can see that coverage has given me the missing branches.


I can tell that coverage is picking up the .coveragerc when run under nose2, because if I remove the branch = True line under the [run] section in .coveragerc, then the branch coverage stats disappear from the report when run under nose.


Am I missing something extra I'm supposed to have done to get this show_missing config to get passed to coverage when it is run under nose2?

versions installed

cov-core==1.15.0
coverage==4.3.4
nose2==0.6.5
1

There are 1 best solutions below

0
On BEST ANSWER

tl;dr - have to add coverage-report = term-missing to the [coverage] section in the unittest.cfg (or other --config [CONFIG], -c [CONFIG] file) for nose2. In order for Cov-Core to pass show_missing = True to coverage


Longer explanation:

When running coverage report on the command-line, show_missing is passed into coverage.coverage()* as None unless overridden in the command line arguments.

However nose2 uses cov-core, which will pass show_missing to coverage.coverage()* in cov_core.CovController.summary() as either True or False. Based upon the following logic:

if 'term' in self.cov_report or 'term-missing' in self.cov_report:
    show_missing = 'term-missing' in self.cov_report
    self.cov.report(show_missing=show_missing, ignore_errors=True, file=stream)

cov_report is that coverage-report config set in nose2.

So this is my confusion because I was trying to use coverage's configs to yield missing lines/branches (when doing a report to term, there's an extra flag for show_missing), when Cov-Core treats them as separate reports (either report term to get plain coverage, or term-missing to get plain coverage + missing lines).

So don't let yourself be bitten by this bit of coverage behaviour Cov-Core has decided to override, when most other bits (include/exclude branch coverage for one) are still driven by coverage's configs.


*coverage.coverage() is a backwards compatability tweak, and is actually an import (in coverage/__init__.py) for coverage.control.Coverage()