You need to test those two pesky lines at the end of your app, if you want 100% code coverage. For dynamically typed languages it is the absolute necessity to have 100% code coverage. Runtime type-checking will push all typos in names of functions and variables into runtime. You really need testtime protection against typos.

If you think that two untested lines of code at the end of your application wouldn’t hurt you, just think about those:

if __name__ == _main__:  # single underscore
    main()

or this:

if __name__ == __main__:
    sys.exit(main())  # forgot to import sys

or this:

if __name__ == __main__:
    sys.exit(main)  # forgot to call main

All of them will cause errors only in a runtime and they silently pass normal module import. So you need to test them. You need to execute them at the test stage, at least once.

How? Here is a link to show you all opinions on this topic: Stackoverflow question.

I used idea from one of answer to that question to create a comprehensive test for __main__ lines. Application code (module.py inside myapp):

Application code (module.py inside myapp):

import sys

def main():
  print("Hello world!")

def init():
  if __name__ == __main__:
    sys.exit(main())

init()

Test code:

import mock
import pytest

def test_init():
  from myapp import module
  with mock.patch.object(module, "main", return_value=42):
    with mock.patch.object(module, "__name__", "__main__"):
      with mock.patch.object(module.sys,'exit') as mock_exit:
         module.init()
         assert mock_exit.call_args[0][0] == 42

This rather bulky test assures that our init function does everything it should:

  1. Really calls main if we have __name__ equals to __main__
  2. Returns it return value as exit code
  3. Does not call main() otherwise.

The final line of the code, the init() call will run at the module import time and, therefore, is run at testtime.

This gives us 100% code coverage provided we have tested main() and the rest of the module code.

Credits to George Shuklin for the original article.

Related Posts

  • Testing exceptions in pytest
  • Making a unique list in Python preserving the order
  • Annotate Querysets to Fetch Specific Values
  • Assert vs require in testify
  • Optimize Database Calls with Prefetch Related and Select Related