Ensuring py.test includes the application directory in sys.path
pytest, python, unit-testing
Solution
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, or `add2virtualenv .` 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.
Problem
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.