django_coverage_plugin
django_coverage_plugin copied to clipboard
Custom template tags not covered
I have some custom template tags and filters. When I disable django_coverage_plugin or downgrade to version 1.3.1, all the code in the templatetags directory is marked as covered, as expected, but as of version 1.4.1 only the function body is marked as covered (which is sort of impossible):
https://coveralls.io/builds/9886572/source?filename=busstops%2Ftemplatetags%2Furlise.py
I'm using Django 1.10.5 and coverage.py 4.3.4.
Thanks for your issue report. There have been a number of similar reports. Late last night I found a fix for at least one of the potential initialization issues. I expect to create a PR with that fix tonight
Could you try with PR https://github.com/nedbat/django_coverage_plugin/pull/38? Thanks.
Background: Since version 1.8, Django has been deferring initialization steps later and later in the process.
Since these changes are all internal to Django, they are not always mentioned in the various release notes, so there's a bit of "whack a mole" trying to find issues. And one-time initialization order issues are very hard to write unit tests for :( (See PR https://github.com/nedbat/django_coverage_plugin/pull/37 for an attempt to test these paths)
No luck with #38. Commenting out lines 166 and 169 of plugin.py fixes the problem for me, though I don't understand why.
@jclgoodwin Thanks for trying. I'll dig in some more and get back to you with another attempt.
<grumble>django gets more efficient at startup ... and more confusing</grumble> :)
@jclgoodwin Do you have a working example I could test against? Or at least your settings.TEMPLATES configuration?
I've added a template tag to my "insane_integration" test branch, but it works correctly.
Commenting out those two lines will prevent check_debug from executing. check_debug validates that the templates are (a) only using the standard Django Template Engine and (b) said engine is configured to be in debug mode.
Yes: https://github.com/jclgoodwin/bustimes.org.uk/blob/master/buses/settings.py#L132
Hello,
Just my two cents. I am seeing this problem still with version 1.5.0 and Django 1.11.7 and coverage 4.4.1.
My observation is that if the custom tags are loaded into a template, it does not break anything. But when they are used, it leads to the whole template being marked as not covered at all.
Any idea how I can try to debug it? Unfortunately the project I am working on is not yet public.
I've just noticed that https://github.com/TauPan/pytest-django-xdist-cov-bug also seems to reproduce this issue. At least I noticed that I see no coverage for home.html which uses a custom template tag. (Thinking about filing https://github.com/pytest-dev/pytest-cov/issues/285 against this repo, too, but that's still undecided.)
This is still an issue for me using:
- django 3.11
- python 3.9
- coverage 5.3
- django-coverage-plugin 1.8
What workarounds are available?
I tried just adding # pragma: no coverage comments to the lines which were getting flagged as uncovered but I knew were obviously getting covered, IE, function definition lines, but that resulted in it skipping measuring whether the bodies of those functions were covered, effectively meaning the file was completely excluded.
So I spent the past 3 hours putting way too much effort into learning about the Coverage API and writing this function which is janky but seems to work for me:
def fixTagCoverage(self):
from coverage import CoverageData
cd = CoverageData()
cd.read()
arcData = {}
for filename in cd.measured_files():
if not 'tag' in filename:
continue
arcsToAdd = []
priorLine = -1
with open(filename) as f:
for i, line in enumerate(f.readlines(), start = 1):
if line.startswith('from ') or line.startswith('register = Library()') or line.startswith('@register.') or line.startswith('def '):
arcsToAdd.append((priorLine, i))
priorLine = i
arcsToAdd.append((priorLine, -1))
arcData[filename] = arcsToAdd
cd.add_arcs(arcData)
cd.write()
It's not documented anywhere, but if you're measuring branch coverage, you must add arcs. Trying to add lines in instead gives back an error message.
This is all executed as part of a larger customer Django management function I've written... here's the lines around the one where this function is called:
def runPythonTestsWithCoverage(self):
omitS = f'--omit={",".join(self.omitFiles + [d + "/*" for d in self.omitDirs])}'
run(['coverage', 'run', '--branch', "--source='.'", omitS, 'manage.py', 'test', 'myapp']).check_returncode()
self.fixTagCoverage() # <<<<<<<<<<<<<<<<<<<<<<<<<<< Where I call the function I just wrote
run(['coverage', 'report', omitS, '-m', '--skip-covered', '--fail-under=100']).check_returncode()
run(['coverage', 'xml', omitS])