Coder Perfect

‘ImportError: No module named YadaYadaYada’ using pytest ‘ImportError: No module named YadaYadaYada’

Problem

I installed pytest on a mac with easy install and began creating tests for a project with the following file structure:

repo/
   |--app.py
   |--settings.py
   |--models.py
   |--tests/
          |--test_app.py

When you run py.test in the repo directory, everything works as expected.

However, when I attempt the same thing on linux or windows (both of which have pytest 2.2.3 installed), it barks whenever it tries to import something from my application path for the first time. Let’s say you want to import some def in app from an app.

Is it necessary for me to change my PATH in order to run py.test on these systems? Has anyone had a similar experience?

Asked by MattoTodd

Solution #1

I’m not sure why py.test doesn’t include the current directory in the PYTHONPATH, but here’s a solution (which should be run from the repository’s root directory):

python -m pytest tests/

Python automatically adds the current directory to the PYTHONPATH.

Answered by Apteryx

Solution #2

Adding an empty file named conftest.py to the repo/ directory is the least invasive solution:

$ touch repo/conftest.py

That is all there is to it. There’s no need to write special code to manipulate the sys.path, remember to drag PYTHONPATH along, or place init .py in places it doesn’t belong (although Apteryx’s approach of using python -m pytest is an excellent solution!).

After that, here’s the project directory:

repo
├── conftest.py
├── app.py
├── settings.py
├── models.py
└── tests
     └── test_app.py

pytest looks for the conftest modules on test collection to gather custom hooks and fixtures, and in order to import the custom objects from them, pytest adds the parent directory of the conftest.py to the sys.path (in this case the repo directory).

If your project has a different structure, put conftest.py in the package root dir (the one that contains packages but does not have a init .py), for example:

repo
├── conftest.py
├── spam
│   ├── __init__.py
│   ├── bacon.py
│   └── egg.py
├── eggs
│   ├── __init__.py
│   └── sausage.py
└── tests
     ├── test_bacon.py
     └── test_egg.py

Although this method can be used with the src layout (put conftest.py in the src directory), it is not recommended.

repo
├── src
│   ├── conftest.py
│   ├── spam
│   │   ├── __init__.py
│   │   ├── bacon.py
│   │   └── egg.py
│   └── eggs 
│       ├── __init__.py
│       └── sausage.py
└── tests
     ├── test_bacon.py
     └── test_egg.py

Be aware that adding src to PYTHONPATH dilutes the src layout’s meaning and benefits! You’ll end up testing the code from the repository rather than the package you installed. Maybe you don’t need the src dir at all if you need to do it.

Of course, conftest modules are more than simply some files to aid in source code discovery; they’re also where all of the project-specific pytest framework additions and test suite customisation take place. The docs for pytest have a lot of information on conftest modules; start with conftest.py: local per-directory plugins.

In addition, SO has a great question about conftest modules: What is the purpose of the conftest.py files in py.test?

Answered by hoefling

Solution #3

The same thing happened to me. I solved the problem by creating an empty init .py file in my testing directory.

Answered by Aron Curzon

Solution #4

If you cd to the tests directory, the source folder is not in Python’s path.

You have two options:

Answered by Not_a_Golfer

Solution #5

python -m pytest tests python -m pytest tests python -m pytest tests python -m pytest tests python

Answered by Stefano Messina

Post is based on https://stackoverflow.com/questions/10253826/path-issue-with-pytest-importerror-no-module-named-yadayadayada