Home > OS >  Pytest --doctest-modules executes scripts
Pytest --doctest-modules executes scripts

Time:11-10

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?

CodePudding user response:

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"]
  • Related