[Tutor] How to write tests for main() function that does not return anything
Steven D'Aprano
steve at pearwood.info
Wed Feb 3 08:20:54 EST 2016
On Tue, Feb 02, 2016 at 10:46:04AM +0000, Pedro Miguel wrote:
> Hi guys, I'm trying to test the code in the main() but I'm a bit
> unsure how to go about it since I'm not passing any arguments or even
> returning anything other then logging. For the purposes of the example
> I've shortened the tree statements in the function.. Can anyone point
> me in the right direction on how to test the logic below?
That's a great question!
I think the right answer is that testing main() is *not* a unit test,
it's an integration test. You're testing that the application as a whole
works the way you expect, rather than testing individual units of the
application (functions, class, methods, modules).
Nevertheless, you could use unittest to test this. Suppose you have a
script which reads some files as input, and then writes some files as
output. You could use the unittest library to give you this integration
test:
import unittest
class MainTest(unittest.TestCase):
def setUp(self):
# set up the environment needed for the test
def test_main(self):
result = os.system("python myscript.py")
self.assertEqual(result, 0)
# now check that the script's output is what you expect
def tearDown(self):
# clean up after the test
But I wouldn't include it in your unit testing module, I would write it
as a separate test file, and probably wouldn't bother using the unittest
library since it doesn't give you any real benefit here:
# myscript_integration_test.py
setup()
result = os.system("python myscript.py")
if result:
print "Integration test failed!"
check_output()
teardown()
Of course, a real test will be more complex. It would need to test each
of the applications command line options, test whether it works
correctly with any environment variables it uses. Test whether it logs
as expected, whether it handles bad input as expected, etc. It will
probably be quite slow, so you don't want to run it as often as your
unit tests and regression tests.
In my opinion, your unit tests should limit themselves to checking that
main() actually exists. You shouldn't assume that
from myscript import main
main()
will work correctly. For example, a lot of scripts or applications
perform setup in the module, like this:
if __name__ == '__main__':
import sys
args = sys.argv[1:]
process(args)
setup_logging()
sys.exit(main(args))
which is hard to unit test. (You could, I guess, use a strict rule that
"main() is the only thing that appears inside the `if __name__...`
block", and if that rule works for you, great, but for me it feels a bit
too restrictive.
Hope this helps,
--
Steve
More information about the Tutor
mailing list