Python unittest for modules

Viewed 53

I want to run a Python unittest by invoking the

python -m unittest discover 

command. Two packages are in in a module as follows

test
 |_ mytest.py
my_module
  |__foo.py
  |__bar.py 

where in bar.py

#bar.py
from foo import baz
# Do things using baz

The problem is that when the unittest discover command runs, foo cannot be found in bar.py anymore. This because my_module is seen as a proper module inside the python test, so I would need to do

from my_module.foo import baz

but that wouldn't work when using the module stand-alone. So what to do? I see 2 options, but they are not that neat so I would like more input:

  1. Let init.py in my_module add my_module to PYTHONPATH
  2. Let mytest.py add my_module to PYTHONPATH

However, I found this page stating that

Never add a package directory, or any directory inside a package, directly to the Python path.

The arguments put forth seems to make sense, and as our repository grows constantly we should try to get this right.

What would you do?

2 Answers

If you ALSO want to have those modules STANDALONE, then they should NOT be INSIDE another module. Because that way, you are ALREADY violating "Never add a page directory inside a module..." And then you could add that path to the pythonpath as well.

If you don't want to make any changes to my_module to turn it into a package that can be imported by your unit tests, one solution is to move your unit tests into my_module. For example, you could have:

# my_module/bar.py

from foo import baz
# my_module/test_bar.py

import bar

# Tests...

Then run python -m unittest discover from inside my_module or python -m unittest discover --start-directory my_module from the project root.

By the way, I think there might be some confusion with terminology here. In Python, a module is typically a single .py file, and a package is typically a folder that contains a group of .py files, one of which is __init__.py. For that reason, foo and bar are probably really modules, and my_module is probably a package (or would be if it had an __init__.py file).

Related