Monday 14 December 2020

Test discovery drops Python namespaces from relative imports?

I encountered a strange issue with unit tests in a namespaced package. Here's the basic structure:

$ tree -P '*.py' src 
src
└── namespace
    └── testcase
        ├── __init__.py
        ├── a.py
        ├── sub
        │   ├── __init__.py
        │   └── b.py
        └── tests
            ├── __init__.py
            └── test_imports.py

4 directories, 6 files

I would expect that relative imports within a namespaced package would maintain the namespace. Normally, that seems to be true:

$ cat src/namespace/testcase/a.py 
print(__name__)
$ cat src/namespace/testcase/sub/b.py 
print(__name__)

from ..a import *
$ python -c 'from namespace.testcase.sub import b'
namespace.testcase.sub.b
namespace.testcase.a

But if I involve a test, I get a surprise:

$ cat src/namespace/testcase/tests/test_imports.py 
from namespace.testcase import a
from ..sub import b
$ python -m unittest discover src/namespace/
namespace.testcase.a
testcase.sub.b
testcase.a

----------------------------------------------------------------------
Ran 0 tests in 0.000s

OK

The code in src/namespace/testcase/a.py is getting run twice! In my case, this caused a singleton I had stubbed to be re-initialized as a real object, subsequently causing test failures.

Is this expected behavior? What is the correct usage here? Should I always avoid relative imports (and have to do global search-and-replace if my company decides to rename something?)



from Test discovery drops Python namespaces from relative imports?

No comments:

Post a Comment