Never-executed line of code mistakenly marked as covered

Issue #468 invalid
Marius Gedminas created an issue

I have coverage.py version 4.0.3 here. I'm using it to compute test coverage of a (sadly not open-source) Django project:

bin/coverage erase
bin/coverage run bin/django test
bin/coverage html --directory=htmlcov

There's a .coveragerc that enables branch coverage:

[run]
source = src/myproject
omit = src/myproject/migrations/*,src/myproject/settings.py
branch = true

The coverage report shows that all lines of code in this method in my models.py are covered:

    def assign_services(self, new_services): 
        new_services = set(new_services) 
        old_services = set(self.services.all()) 
        to_add = new_services - old_services 
        to_remove = old_services - new_services 
        for service in to_remove: 
            self.services.get(service=service).delete()      # <-- bug here
        for service in to_add: 
            SampleService.objects.create(sample=self, service=service) 

That is not correct. Any attempt to call self.services.get(service=service) would raise an exception, which would show up as a failed test. That doesn't happen. Attempts to insert a raise AssertionError inside the for loop body, above that line, prove that the for loop body is never executed, despite coverage thinking that it is.

I haven't been able to reproduce this with a smaller code example :(

Comments (2)

  1. Marius Gedminas reporter

    Oops, I filed this too soon. I came up with the idea of testing pdb.set_trace() instead of just a raise AssertionError, and, well, the test suite is slow and I didn't wait for it to finish running before I finished tweaking the description and hit Submit.

    Needless to say, pdb.set_trace() shows that coverage.py is absolutely correct: that line of code is executed, and it raises the error -- which is then somehow silently captured and ignored because my test suite is buggy. Of course.

  2. Log in to comment