There were already questions regarding this topic. Sometimes programmers put some __init__.py
at some places, often it is said one should use absolute paths. However, I don't get it to work here:
How do I import a class from a package so that tests in pytest run and the code can be used?
At the moment I get pytest or the code passing respective running.
My example project structure is
.
├── testingonly
│ ├── cli.py
│ ├── __init__.py
│ └── testingonly.py
└── tests
├── __init__.py
└── test_testingonly.py
__init__.py
is in both cases an empty file.
$ cat testingonly/cli.py
"""Console script for testingonly."""
from testingonly import Tester
def main(args=None):
"""Console script for testingonly."""
te = Tester()
return 0
main()
$ cat testingonly/testingonly.py
"""Main module."""
class Tester():
def __init__(self):
print("Hello")
This gives - as expected:
$ python3 testingonly/cli.py
Hello
Trying to test this, however, fails:
$ pytest
========================================================= test session starts =========================================================
platform linux -- Python 3.7.3, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /home/stefan/Development/testingonly
collected 0 items / 1 error
=============================================================== ERRORS ================================================================
_____________________________________________ ERROR collecting tests/test_testingonly.py ______________________________________________
ImportError while importing test module '/home/stefan/Development/testingonly/tests/test_testingonly.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.7/importlib/__init__.py:127: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
tests/test_testingonly.py:10: in <module>
from testingonly import cli
testingonly/cli.py:2: in <module>
from testingonly import Tester
E ImportError: cannot import name 'Tester' from 'testingonly' (/home/stefan/Development/testingonly/testingonly/__init__.py)
Renaming testingonly/testingonly.py
to testingonly/mytest.py
and changing the imports in test_testingonly.py (from testingonly import mytest) and cli.py (from mytest import Tester) gives
$ pytest
========================================================= test session starts =========================================================
platform linux -- Python 3.7.3, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /home/stefan/Development/testingonly
collected 0 items / 1 error
=============================================================== ERRORS ================================================================
_____________________________________________ ERROR collecting tests/test_testingonly.py ______________________________________________
ImportError while importing test module '/home/stefan/Development/testingonly/tests/test_testingonly.py'.
Hint: make sure your test modules/packages have valid Python names.
Traceback:
/usr/lib/python3.7/importlib/__init__.py:127: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
tests/test_testingonly.py:10: in <module>
from testingonly import cli
testingonly/cli.py:2: in <module>
from mytest import Tester
E ModuleNotFoundError: No module named 'mytest'
======================================================= short test summary info =======================================================
ERROR tests/test_testingonly.py
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
========================================================== 1 error in 0.37s ===========================================================
$ python3 testingonly/cli.py
Hello
The other proposed solution with renaming to mytest.py lets the tests pass, but in cli.py using from testingonly.mytest import Tester
gives a NameNotFound error.
$ python3 testingonly/cli.py
Traceback (most recent call last):
File "testingonly/cli.py", line 2, in <module>
from testingonly.mytest import Tester
ModuleNotFoundError: No module named 'testingonly'
$ pytest
========================================================= test session starts =========================================================
platform linux -- Python 3.7.3, pytest-6.2.5, py-1.11.0, pluggy-1.0.0
rootdir: /home/stefan/Development/testingonly
collected 1 item
tests/test_testingonly.py . [100%]
========================================================== 1 passed in 0.12s ==========================================================
from testingonly import Tester
is wrong. TheTester
class is defined in module with qualnametestingonly.testingonly
as is not exported intestingonly/__init__.py
, so the import will not resolve. It works intestingonly.cli
only because it is on the same level astestingonly.testingonly
, with a relative import as fallback. To verify, create somefoo.py
in the root dir with a single linefrom testingonly import Tester
and runpython foo.py
- you will get the same error. – Animalitypytest
doesn't add the project root dir tosys.path
by default - you should take care of it yourself. Either runpython -m pytest
, or add an empty file namedconftest.py
to the project root dir. Check out the answers in PATH issue with pytest 'ImportError: No module named YadaYadaYada' for more details. – Animalityfrom testingonly import Tester
is of coursefrom testingonly.testingonly import Tester
– Animality