pytest "--import-mode=importlib" Changes Imports and Breaks Tests in CI
pytest’s --import-mode controls how test modules are imported. The default prepend mode inserts directories onto sys.path; importlib mode does not, so tests that relied on implicit sys.path entries fail to import the package under test.
What this error means
After setting --import-mode=importlib (or upgrading to a config that defaults to it), tests fail at collection with ModuleNotFoundError for the package under test or a conftest, even though the files exist. Switching back to prepend, or installing the package, fixes it.
ERROR collecting tests/test_api.py
ModuleNotFoundError: No module named 'myapp'
# worked under --import-mode=prepend, fails under importlibDiagnose it: what did pytest actually collect?
Most pytest failures that only happen in CI are collection or import-path problems rather than test failures. The runner has a different working directory, a different sys.path, and usually no editable install, so a test module that imports your package locally may not resolve at all.
# what would run, without running it
pytest --collect-only -q | tail -20
# where pytest thinks the root is (drives conftest and import mode)
pytest --collect-only 2>&1 | grep -i rootdir
# is the package importable at all from the runner cwd?
python -c "import yourpackage, sys; print(yourpackage.__file__)"
python -c "import sys; print(sys.path)"Common causes
importlib mode does not modify sys.path
Unlike prepend/append, importlib mode imports tests without inserting their directories onto sys.path. Code relying on that implicit path no longer resolves the package.
Package not installed, only on an implicit path
If the project was never installed (pip install -e .) and relied on prepend adding the rootdir, importlib mode has no path to it.
How to fix it
Install the project so imports resolve regardless of mode
An editable install puts the package on sys.path properly, which importlib mode (and a src-layout) expects.
pip install -e .
pytest --import-mode=importlibSet the import mode explicitly and consistently
Pin the mode in config so local and CI behave the same.
[tool.pytest.ini_options]
addopts = "--import-mode=importlib"
pythonpath = ["src"] # if not installing the packageMake a zero-test run fail the build
# fail explicitly when nothing is collected
pytest --strict-markers -q
test "${PIPESTATUS[0]}" -ne 5 || { echo "pytest collected no tests"; exit 1; }How to prevent it
- Install the project (editable is fine) rather than relying on implicit
sys.path. - Pin
--import-modein config so it is consistent across environments. - Adopt a src-layout with
importlibmode for clean import isolation.