问题
I have a project directory structure as follows (which I think is pretty standard):
my_project
setup.py
mypkg
__init__.py
foo.py
tests
functional
test_f1.py
unit
test_u1.py
I'm using py.test for my testing framework, and I'd expect to be able to run py.test tests
when in the my_project
directory to run my tests. This does indeed work, until I try to import my application code using (for example) import mypkg
in a test. At that point, I get the error "No module named mypkg". On doing a bit of investigation, it appears that py.test
runs the tests with the directory of the test file in sys.path
, but not the directory that py.test
was run from.
In order to work around this, I have added a conftest.py
file to my tests
directory, containing the following code:
import sys, os
# Make sure that the application source directory (this directory's parent) is
# on sys.path.
here = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, here)
This seems to work, but is it a good way of making sure that the tests see the application code? Is there a better way of achieving this, or am I doing something wrong in how I have my project structured?
I've looked at some other projects that use py.test
(for example, pip
) but I can't see code that does anything like this, and yet running py.test tests
seems to work there. I don't know quite why, but I'm worried that they may have achieved the same result in a simpler way.
I've looked in the py.test
documentation, but I can't see an explanation of this problem or what the recommended approach is to deal with it.
回答1:
As you say yourself py.test basically assumes you have the PYTHONPATH setup up correctly. There are several ways of achieving this:
Give your project a setup.py and use
pip install -e .
in a virtualenv for this project. This is probably the standard method.As a variation on this if you have a virtualenv but no setup.py use your venv's facility to add the projects directory on sys.path, e.g.
pew add .
if you use pew, oradd2virtualenv .
if you use virtualenv and the extensions of virtualenvwrapper.If you always like the current working directory on sys.path you can simply always export
PYTHONPATH=''
in your shell. That is ensure the empty string on on sys.path which python will interpret as the current working direcotry. This is potentially a security hazard though.My own favourite hack, abuse how py.test loads conftest files: put an empty
conftest.py
in the project's top-level directory.
The reason for py.test to behave this way is to make it easy to run the tests in a tests/ directory of a checkout against an installed package. If it would unconditionally add the project directory to the PYTHONPATH then this would not be possible anymore.
回答2:
The answer is actually much easier, as seen here.
All you need to do is add an __init__.py
to your test directory and each of its sub directories, like so;
tests/__init__.py
tests/functional/__init__.py
tests/unit/__init__.py
回答3:
The easy way of doing it is, in terminal/cmd change directory to where the parent directory is, (e.g. in this case cd C:/.../my_project
).
Then run:
python -m pytest --cov=mypkg tests
No need to mess with the PYTHONPATH
environment variable.
By running with python -m pytest
, it automatically adds the current directory to sys.path
.
来源:https://stackoverflow.com/questions/20971619/ensuring-py-test-includes-the-application-directory-in-sys-path