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.

oz123
  • 27,559
  • 27
  • 125
  • 187
Peter de Rivaz
  • 33,126
  • 4
  • 46
  • 75
  • 4
    Why don't you just `pip install coverage` and use that? It will give you a nice HMTL report that highlights missed lines etc. – jonrsharpe Aug 29 '15 at 18:51
  • 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. – Peter de Rivaz Aug 29 '15 at 18:54
  • 3
    Well you could just `assert False`, then if the exception never gets thrown you didn't hit that line. – jonrsharpe Aug 29 '15 at 18:55

1 Answers1

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%
Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
f.rodrigues
  • 3,499
  • 6
  • 26
  • 62