Is it possible to make a code coverage assertion in Python?
Asked Answered
S

1

6

When I am writing tests or debugging code I would like to be able to add a line of Python that will notify me if that line is never executed. Is this possible?

For example, I want to be able to write code such as:

def f(x):
   if x==0:
      check_covered()
      return 1
   elif x==1:
      check_covered()
      return 2
   else:
      check_covered()
   return 3

f(1)
f(2)
print_all_missing_cases()

And I would like the output to tell me that one of the branches has never been covered.

What I've tried

Approach 1

I can do this for functions with a decorator as follows:

missing_fns = set()

def covered(h):
    missing_fns.add(h.func_name)
    def h2(*args):
        missing_fns.remove(h.func_name)
        return h(*args)
    return h2 

@covered
def f(a):
    return a+1

@covered
def g(a):
    return a+2

f(0)
for x in missing_fns:
    print x,'is never called'

But I am struggling to find something that is activated during the compilation of a function that I would be able to hook into.

Approach 2

It is also quite straightforward if I pass in an incrementing value to each instance (e.g. check_covered(0), check_covered(1), check_covered(2),...) but this gets messy when I copy or delete code.

Approach 3

It is possible to get this information by running a code coverage tool but if possible I would prefer to do this with some simple Python code that I have a chance of understanding.

Subito answered 29/8, 2015 at 18:22 Comment(3)
Why don't you just pip install coverage and use that? It will give you a nice HMTL report that highlights missed lines etc.Lyndonlyndsay
That may well be the best approach, but I was curious whether it was possible without such a heavyweight approach - e.g. when debugging I would like to be able to add asserts in certain places to check they are being covered.Subito
Well you could just assert False, then if the exception never gets thrown you didn't hit that line.Lyndonlyndsay
U
5

I highly recommend using the coverage module.

There's a nice tutorial on how to get the best result here

Usage is simple:

$ coverage run my_program.py arg1 arg2

Than see the results with coverage report

$ coverage report -m
Name                      Stmts   Miss  Cover   Missing
-------------------------------------------------------
my_program                   20      4    80%   33-35, 39
my_other_module              56      6    89%   17-23
-------------------------------------------------------
TOTAL                        76     10    87%
Ulbricht answered 29/8, 2015 at 19:13 Comment(2)
@Peter There was an additional https there. I have fixed itLisa
Additionally I'd like to add a link to the coverage package page.Lisa

© 2022 - 2024 — McMap. All rights reserved.