Search code examples
pythoncode-coveragecoverage.py

What is a partial hit in code coverage?


Recently, when switching from Coveralls to Codecov coverage in my project dropped by a few percent. This seems to be due to partial hits, which are counted as hits in Coveralls but as misses in Codecov.

Here is a code example:

class Struct(object):                  # hit
    def __init__(self, content=None):  # hit            
        if content is not None:        # partial hit
            self.content = content     # missed

s = Struct()                           # hit

As far I see, the if statement is fully evaluated by the interpreter. Why is it not counted as a hit, then?


Solution

  • It means that on that line there is a branching statement but one of the branches was never executed.

    From the following line, it is obvious that the content was not ever given to that constructor, so you never tested the code with Struct(content=something).

    Note also that if you do not give an argument, self.content will not be set, and thus AttributeError will be raised if access is attempted.


    While in this case you could deduce it from the statement inside if, were the truth value opposite, you couldn't see that the condition was never false. Consider your example again, slightly modified

    class Struct(object):                  # hit
        def __init__(self, content=None):  # hit            
            if content is not None:        # partial hit
                self.content = content     # hit
    
        def print_content(self):           # hit
            print(self.content)            # hit
    
    s = Struct('42')                       # hit
    s.print_content()                      # hit
    

    Looks like everything is fine? If you didn't use branch coverage, the if would also say "hit", and you wouldn't notice that you never tested the code in the case that content is not None is False, which then would have the bug of not setting the self.content attribute: the following program:

    s = Struct()
    s.print_content()
    

    when run, raises:

    Traceback (most recent call last):
      File "foo.py", line 10, in <module>
        s.print_content()
      File "foo.py", line 7, in print_content
        print(self.content)
    AttributeError: 'Struct' object has no attribute 'content'