PATH issue with pytest ‘ImportError: No module named YadaYadaYada’

Posted on

Solving problem is about exposing yourself to as many situations as possible like PATH issue with pytest ‘ImportError: No module named YadaYadaYada’ and practice these strategies over and over. With time, it becomes second nature and a natural way you approach any problems in general. Big or small, always start with a plan, use other strategies mentioned here till you are confident and ready to code the solution.
In this post, my aim is to share an overview the topic about PATH issue with pytest ‘ImportError: No module named YadaYadaYada’, which can be followed any time. Take easy to follow this discuss.

PATH issue with pytest ‘ImportError: No module named YadaYadaYada’

I used easy_install to install pytest on a mac and started writing tests for a project with a file structure likes so:

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

run py.test while in the repo directory, everything behaves as you would expect

but when I try that same thing on either linux or windows (both have pytest 2.2.3 on them) it barks whenever it hits its first import of something from my application path. Say for instance from app import some_def_in_app

Do I need to be editing my PATH to run py.test on these systems? Has Anyone experienced this?

Answer #1:

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

You have 2 choices:

  1. Add the path manually to the test files, something like this:

    import sys, os
    myPath = os.path.dirname(os.path.abspath(__file__))
    sys.path.insert(0, myPath + '/../')
    
  2. Run the tests with the env var PYTHONPATH=../.

Answered By: Not_a_Golfer

Answer #2:

I’m not sure why py.test does not add the current directory in the PYTHONPATH itself, but here’s a workaround (to be executed from the root of your repository):

python -m pytest tests/

It works because Python adds the current directory in the PYTHONPATH for you.

Answered By: Apteryx

Answer #3:

conftest solution

The least invasive solution is adding an empty file named conftest.py in the repo/ directory:

$ touch repo/conftest.py

That’s it. No need to write custom code for mangling the sys.path or remember to drag PYTHONPATH along, or placing __init__.py into dirs where it doesn’t belong (using python -m pytest as suggested in Apteryx‘s answer is a good solution though!).

The project directory afterwards:

repo
??? conftest.py
??? app.py
??? settings.py
??? models.py
??? tests
     ??? test_app.py

Explanation

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).

Other project structures

If you have other project structure, place the conftest.py in the package root dir (the one that contains packages but is not a package itself, so does not contain an __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

src layout

Although this approach can be used with the src layout (place conftest.py in the src dir):

repo
??? src
?   ??? conftest.py
?   ??? spam
?   ?   ??? __init__.py
?   ?   ??? bacon.py
?   ?   ??? egg.py
?   ??? eggs
?       ??? __init__.py
?       ??? sausage.py
??? tests
     ??? test_bacon.py
     ??? test_egg.py

beware that adding src to PYTHONPATH mitigates the meaning and benefits of the src layout! You will end up with testing the code from repository and not the installed package. If you need to do it, maybe you don’t need the src dir at all.

Where to go from here

Of course, conftest modules are not just some files to help the source code discovery; it’s where all the project-specific enhancements of the pytest framework and the customization of your test suite happen. pytest has a lot of information on conftest modules scattered throughout their docs; start with conftest.py: local per-directory plugins

Also, SO has an excellent question on conftest modules: In py.test, what is the use of conftest.py files?

Answered By: hoefling

Answer #4:

I had the same problem. I fixed it by adding an empty __init__.py file to my tests directory.

Answered By: Aron Curzon

Answer #5:

Run pytest itself as a module with:
python -m pytest tests

Answered By: Stefano Messina

Answer #6:

You can run with PYTHONPATH in project root

PYTHONPATH=. py.test

Or use pip install as editable import

pip install -e .   # install package using setup.py in editable mode
Answered By: Ford Guo

Answer #7:

I created this as an answer to your question and my own confusion. I hope it helps. Pay attention to PYTHONPATH in both the py.test command line and in the tox.ini.

https://github.com/jeffmacdonald/pytest_test

Specifically: You have to tell py.test and tox where to find the modules you are including.

With py.test you can do this:

PYTHONPATH=. py.test

And with tox, add this to your tox.ini:

[testenv]
deps= -r{toxinidir}/requirements.txt
commands=py.test
setenv =
    PYTHONPATH = {toxinidir}
Answered By: Jeff MacDonald

Answer #8:

I had the same problem in Flask.

When I added:

__init__.py

to tests folder, problem disappeared 🙂

Probably application couldn’t recognize folder tests as module

Answered By: user13037517

Leave a Reply

Your email address will not be published. Required fields are marked *