Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test or mock "if __name__ == '__main__'" contents

Say I have a module with the following:

def main():     pass  if __name__ == "__main__":     main() 

I want to write a unit test for the bottom half (I'd like to achieve 100% coverage). I discovered the runpy builtin module that performs the import/__name__-setting mechanism, but I can't figure out how to mock or otherwise check that the main() function is called.

This is what I've tried so far:

import runpy import mock  @mock.patch('foobar.main') def test_main(self, main):     runpy.run_module('foobar', run_name='__main__')     main.assert_called_once_with() 
like image 313
Nikolaj Avatar asked May 01 '11 17:05

Nikolaj


People also ask

How do you take a test case in python?

Create a class called TestSum that inherits from the TestCase class. Convert the test functions into methods by adding self as the first argument. Change the assertions to use the self. assertEqual() method on the TestCase class.

How do you assert equal in Python?

assertEqual() in Python is a unittest library function that is used in unit testing to check the equality of two values. This function will take three parameters as input and return a boolean value depending upon the assert condition. If both input values are equal assertEqual() will return true else return false.


2 Answers

I will choose another alternative which is to exclude the if __name__ == '__main__' from the coverage report , of course you can do that only if you already have a test case for your main() function in your tests.

As for why I choose to exclude rather than writing a new test case for the whole script is because if as I stated you already have a test case for your main() function the fact that you add an other test case for the script (just for having a 100 % coverage) will be just a duplicated one.

For how to exclude the if __name__ == '__main__' you can write a coverage configuration file and add in the section report:

[report]  exclude_lines =     if __name__ == .__main__.: 

More info about the coverage configuration file can be found here.

Hope this can help.

like image 146
mouad Avatar answered Oct 11 '22 20:10

mouad


You can do this using the imp module rather than the import statement. The problem with the import statement is that the test for '__main__' runs as part of the import statement before you get a chance to assign to runpy.__name__.

For example, you could use imp.load_source() like so:

import imp runpy = imp.load_source('__main__', '/path/to/runpy.py') 

The first parameter is assigned to __name__ of the imported module.

like image 31
David Heffernan Avatar answered Oct 11 '22 22:10

David Heffernan