Issue #129 new

Misleading branch coverage of empty methods

Christian Heimes
created an issue

Branch coverage of an abc.abstractmethod with just a doc string in the method, shows the decorator line as uncovered branch that never reaches "exit".

import abc

class AExample(object):
    @abc.abstractmethod  # exit
    def method(self):
        """doc
        """

class Example(AExample):
    def method(self):
        return True

Example().method()

When I replace the doc string with "pass", the decorator line is a covered branch. However the pass statement is not covered at all.

class AExample(object):
    @abc.abstractmethod 
    def method(self): 
        pass  # uncovered

Comments (6)

  1. Ned Batchelder repo owner

    Turns out this isn't about abstract methods, it's about empty uncalled methods with only a docstring:

    class Example(object):
        def method1(self):      # no branch to exit
            """doc"""
    
        def method2(self):
            pass                # not executed
    
        def method3(self):
            """doc"""
            pass                # not executed
    
  2. Alex Gaynor

    It's unclear to me what the correct behavior is, it seems to me it's either a) no executed, or b) covered, but not a branch coverage thing. (b) is somewhat more convenient, but I'm not sure it's more correct.

  3. Manganeez

    (a) would seem more appropriate for a bare function definition with only a docstring, while (b) seems right for an abstractmethod, so perhaps that should be special-cased as the OP suggested.

    Incidentally, it's easy enough to do per-project because the "blamed" lines are the ones with the decorators. In your project .coveragerc:

    [report]
    exclude_lines =
        @abstract
        <whatever_else>
    
  4. Log in to comment