pytest ERROR collecting: ModuleNotFoundError (tested)
ERROR collecting tests/test_x.py ... ModuleNotFoundError: No module named 'myapp' followed by Interrupted: 1 error during collection means pytest could not import your test file because your package is not on sys.path. Set pythonpath in your pytest config (or run python -m pytest for a flat layout, or pip install -e .).
How this was measured
One shell script builds a fresh small project for each case and runs pytest; run shows only the relevant lines of pytest's output (the E line, the summary) and the exit code:
# run from /tmp/pt383; each step makes a fresh copy of the project
export PATH=/tmp/se383/bin:$PATH PYTHONDONTWRITEBYTECODE=1
fresh() { rm -rf p && mkdir -p p/tests && cd p; }
run() { echo "\$ $*"; "$@" -q -p no:cacheprovider 2>&1 | grep -E "^E |passed|error|Interrupted|mismatch|^ERROR"; echo "exit code: ${PIPESTATUS[0]}"; }
case $1 in
flat)
fresh; mkdir myapp; touch myapp/__init__.py; printf 'def add(a, b):\n return a + b\n' > myapp/calc.py
printf 'from myapp.calc import add\n\n\ndef test_add():\n assert add(2, 3) == 5\n' > tests/test_calc.py
find . -type f | sort; run pytest; run python -m pytest ;;
src)
fresh; mkdir -p src/myapp; touch src/myapp/__init__.py; printf 'def add(a, b):\n return a + b\n' > src/myapp/calc.py
printf 'from myapp.calc import add\n\n\ndef test_add():\n assert add(2, 3) == 5\n' > tests/test_calc.py
find . -type f | sort; run python -m pytest
printf '[tool.pytest.ini_options]\npythonpath = ["src"]\n' > pyproject.toml; echo '$ cat pyproject.toml'; cat pyproject.toml; run pytest ;;
dup)
fresh; mkdir tests/api tests/db
printf 'def test_api():\n pass\n' > tests/api/test_utils.py; printf 'def test_db():\n pass\n' > tests/db/test_utils.py
find . -type f | sort; run pytest
touch tests/__init__.py tests/api/__init__.py tests/db/__init__.py; echo '$ touch tests/__init__.py tests/api/__init__.py tests/db/__init__.py'; run pytest ;;
esac
1. Reproduce it: tests/ cannot import your package
./myapp/calc.py
./myapp/__init__.py
./tests/test_calc.py
$ pytest
E ModuleNotFoundError: No module named 'myapp'
ERROR tests/test_calc.py
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
1 error in 0.09s
exit code: 2
$ python -m pytest
1 passed in 0.01s
exit code: 0
Interrupted: 1 error during collection means pytest could not even import a test file, so it ran no tests and exited with code 2. The E line has the real error: ModuleNotFoundError: No module named 'myapp'. In the default import mode pytest puts the test file's own folder (tests/, which has no __init__.py) on sys.path, not the project root, so a package next to tests/ is not importable. python -m pytest also adds the current directory to sys.path, which is why it passes from the project root: the classic "works with python -m pytest, fails with pytest".
2. src layout: python -m pytest is not enough, use pythonpath
./src/myapp/calc.py
./src/myapp/__init__.py
./tests/test_calc.py
$ python -m pytest
E ModuleNotFoundError: No module named 'myapp'
ERROR tests/test_calc.py
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
1 error in 0.09s
exit code: 2
$ cat pyproject.toml
[tool.pytest.ini_options]
pythonpath = ["src"]
$ pytest
1 passed in 0.01s
exit code: 0
With the package under src/, adding the project root does not help. Tell pytest where the code is with the pythonpath setting (in pyproject.toml or pytest.ini): it inserts those directories into sys.path before collection. The other standard fix is installing the project into your virtual environment in editable mode (pip install -e .), which works for every tool, not only pytest.
3. "import file mismatch": two test files with the same name
./tests/api/test_utils.py
./tests/db/test_utils.py
$ pytest
import file mismatch:
ERROR tests/db/test_utils.py
!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!
1 error in 0.09s
exit code: 2
$ touch tests/__init__.py tests/api/__init__.py tests/db/__init__.py
$ pytest
2 passed in 0.01s
exit code: 0
Without __init__.py files both test_utils.py are imported as a top-level module named test_utils, and the second one clashes with the first. Adding __init__.py to the test folders makes them packages, so the modules get distinct names (tests.api.test_utils, tests.db.test_utils). Renaming one file also works.
4. Checklist
- Read the
Eline underERROR collecting: it is an ordinary Python import error. - Run pytest from the project root, in the virtual environment where your dependencies are installed (a
ModuleNotFoundErrorfor a third-party package means pytest runs in another environment: comparewhich pytestandwhich python). - Flat layout:
python -m pytestorpythonpath = ["."]. src layout:pythonpath = ["src"]orpip install -e .. - Same test file names in different folders: add
__init__.pyfiles.
Related: pytest no tests ran (exit code 5), pytest error: unrecognized arguments.
Frequently asked questions
Why does pytest say ModuleNotFoundError when python works?
pytest puts the test file's folder on sys.path, not your project root. python -m pytest adds the current directory too; for a src layout set pythonpath = ["src"] or pip install -e .
What does Interrupted: 1 error during collection mean?
pytest failed to import a test module (the E line shows why), so it stopped before running any tests and exited with code 2.
Written with AI assistance. Measured on 2026-10-23 with pytest 9.1.1 and Python 3.13.5 on Linux. The script was run verbatim and the output pasted unedited. PlainHeaders is our extension; Python and pytest are free.