Testing subpackage modules in Python 3
- by Mitchell Model
I have been experimenting with various uses of hierarchies like this and the differences between absolute and relative imports, and can't figure out how to do routine things with the package, subpackages, and modules without simply putting everything on sys.path. I have a two-level package hierarchy:
MyApp
__init__.py
Application
__init__.py
Module1
Module2
...
Domain
__init__.py
Module1
Module2
...
UI
__init__.py
Module1
Module2
...
I want to be able to do the following:
Run test code in a Module's "if main" when the module imports from other modules in the same directory.
Have one or more test code modules in each subpackage that runs unit tests on the modules in the subpackage.
Have a set of unit tests that reside in someplace reasonable, but outside the subpackages, either in a sibling package, at the top-level package, or outside the top-level package (though all these might end up doing is running the tests in each subpackage)
"Enter" the structure from any of the three subpackage levels, e.g. run code that just uses Domain modules, run code that just uses Application modules, but Application uses code from both Application and Domain modules, and run code from GUI uses code from both GUI and Application; for instance, Application test code would import Application modules but not Domain modules.
After developing the bulk of the code without subpackages, continue developing and testing after organizing the modules into this hierarchy.
I know how to use relative imports so that external code that puts MyApp on its sys.path can import MyApp, import any subpackages it wants, and import things from their modules, while the modules in each subpackage can import other modules from the same subpackage or from sibling packages. However, the development needs listed above seem incompatible with subpackage structuring -- in other words, I can't have it both ways: a well-structured multi-level package hierarchy used from the outside and also used from within, in particular for testing but also because modules from one design level (in particular the UI) should not import modules from a design level below the next one down.
Sorry for the long essay, but I think it fairly represents the struggles a lot of people have been having adopting to the new relative import mechanisms.