Pytest –doctest-modules executes scripts

Question:

I have this MRE:

.
└── tests
    └── notest.py

The notest.py just do a sys.exit(1):

When I run pytest --doctest-modules I get this error:

ERROR collecting tests/notest.py
tests/notest.py:4: in <module>
    sys.exit(1)
E   SystemExit: 1

So the --doctest-modules would try to execute my script which is not a test. Is that normal behaviour and how to prevent that?

Asked By: nowox

||

Answers:

Is that normal behaviour?

Yes. Passing --doctest-modules will activate a special doctest collector that is not restricted to globs specified by python_files (test_*.py and *_test.py by default). Instead, it will find and collect any python module that is not __init__.py or __main__.py. Afterwards, doctest will import them to collect docstrings and execute doctests from every module.

how to prevent that?

If you have doctests in notest you want to run, you have to prevent code execution on notest module import. Place the code that causes premature exit into if __name__ == '__main__' block:

# notest.py
import sys

if __name__ == '__main__':
    sys.exit(1)

Now the regular import (e.g. python -c 'import tests.notest') will exit with 0 as the main block is not executed, while running the module (e.g. python tests/notest.py or python -m tests.notest) will still exit with 1.


If you have no tests in the notest module or you can’t edit its code, you can instruct pytest to ignore the module completely:

$ pytest --doctest-modules --ignore=tests/notest.py

or persist the option in pyproject.toml or pytest.ini to avoid entering the option every time. Example with pyproject.toml:

[tool.pytest.ini_options]
addopts = "--ignore=tests/notest.py"

Alternatively, this can also be done in a conftest module. Example:

# tests/conftest.py
collect_ignore = ["notest.py"]

Beware that collect_ignore receives files relative to the current conftest module. Therefore, if you use a conftest in the project root directory (on the same level as tests directory), you would have to specify the correct relative path:

# conftest.py
collect_ignore = ["tests/notest.py"]
Answered By: hoefling
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.