I'm trying to setup a project (Python 3.4.4, pytest 3.3.1) to use pytest, but pytest is failing to run tests in a file or a directory. I think I'm using pytest wrong, but am not what the correct workflow would be.
What I've tried
Following the suggestions in "Good Integration Practices" and also due to the personal preference of having the source and the tests in separate folders, I have setup my project as follows:
parent_directory/
setup.py
src/
project_name/
__init__.py # empty
utils.py
tests/
__init__.py # empty
project_name/
__init__.py # empty
test_utils.py # has `import project_name.utils.py`
With this exact setup, "Usage and Invocations" says I should be able to run the tests using
python -m pytest
and that pytest will add the current directory to sys.path
("except that calling via python will also add the current directory to sys.path."). If I try to do that from parent_directory/src
, no tests are collected (collected 0 items
). If I do that from parent_directory/
, I get ImportError: No module named 'project_name'
.
After some reading -- (see "Test root path"), I have found out that adding (an empty) conftest.py
to src/
"will have pytest recognizing your application modules without specifying PYTHONPATH".
After doing this, I can go to parent_directory/
and successfully run
pytest
and
pytest -k test_some_specific_test_function_name
Notice that I could switch from python -m pytest
to just pytest
, which I'm happy about.
However, if I try to run tests in a specific file (or directory), e.g.
pytest tests/project_name/test_utils.py
I, once again, get ImportError: No module named 'project_name'
. This behavior is quite surprising to me.
I have checked:
- pytest cannot find package when I put tests in a separate directory - different dir structure
- PATH issue with pytest 'ImportError: No module named YadaYadaYada' (first suggestion is the
sys.path
"hack", second is an environment variable, which is not practical if one works on multiple projects simultaneously -- surely there's a better way) - Py.test No module named * - different dir structure
Question
What would be the correct workflow that would allow me to preserve my directory structure while, ideally from parent_directory/
, being able to call all of:
pytest
pytest -k test_some_specific_test_function_name
pytest tests/project_name/test_utils.py
without some manual sys.path
hacking.
I'm sure I'm missing something obvious. Thanks!
Pytest will add the current directory to sys.path
, but that doesn't necessarily mean that it makes your package importable from the source tree. In fact, the entire point of using a src
and test
layout is to prevent pytest from testing against the source tree.
You can check this yourself by running a python interpreter from the top-level directory of your project and attempting to import the package. It won't work, unless it has already been installed in your working environment.
By using the src
and test
layout, pytest is forced to test against an installed version of your package. See this great blog post with motivation for structuring your project this way. Here's the key paragraph:
You will be forced to test the installed code (e.g.: by installing in a virtualenv). This will ensure that the deployed code works (it's packaged correctly) - otherwise your tests will fail. Early. Before you can publish a broken distribution.
So if you want to use this kind of layout for your project, you need to install your package before testing. There are advantages and disadvantages to either approach, but pytest recommends it and I'm inclined to agree.
[update]
As a workaround for convenient local testing, you can install your package in development mode using either setup.py develop
or pip install -e .
. This makes your package appear to be installed in your environment, but any updates in your source tree will be immediately reflected in the "installed" version.1
If you choose to follow this approach, you should make sure that you are using a sandboxed development environment (e.g. virtualenv
or conda
) so that you don't pollute your system environment.
1 You should be aware that if your package provides and C/C++ or Cython extensions, they will need to be rebuilt manually.
来源:https://stackoverflow.com/questions/47859986/usual-pytest-workflow-cant-run-tests-in-a-file