Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
602 views
in Technique[技术] by (71.8m points)

python - Usual pytest workflow - can't run tests in a file

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:

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!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...