PATH issue with pytest 'ImportError: No module named YadaYadaYada'

pytest conftest
pytest example
hint: make sure your test modules/packages have valid python names.
modulenotfounderror: no module named 'pytest' pycharm
pytest documentation
pytest setup
pytest environment variables
pytest multiple files

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?

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=../.

PATH issue with pytest 'ImportError: No module named , Yes, the source folder is not in Python's path if you cd to the tests directory. You have 2 choices: Add the path manually to the test files,  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).

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.

pytest cannot import module while python can, I had one such file, deleting it solved the problem. This was actually buried in the comments to the second answer of PATH issue with pytest '  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

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.

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?

conftest.py in root directory should not add root directory to sys.path , ini , and file path for the files in the test directory are being incorrectly calculated while running tests. For eg. Expected path: c:\Users\luabud\Apps\  Without CLI options, the pytest.ini is found (first assertion in the test passes): With a path that is part of a custom py.test CLI option, pytest.ini discovery fails:

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

Testing with pytest always issues a file not found error · Issue #6548 , There are two ways to handle this problem, described below. Automatic looking for of Django projects¶. By default, pytest-django tries to find Django projects by  pytest>=5.1.0 is unable to locate test nodes in modules when executed programmatically from a wheel installed on a Windows mapped network drive, if more than one node is passed to pytest.main platform: windows type: regression. #5835 opened Sep 9, 2019 by paul-ko.

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

Managing the Python path, insert(0, path) . Note that using the site_dirs will not place your specified paths in front of existing paths. Once this is added to your pytest.ini,  Hi, great project! 👍 Thanks for all the efforts! I would suggest to add another tip to your great site: how to correctly use patch and pytest.mark.parametrize at the same time. Here is a small, stupid test snippet: import os.path from un

pytest-pythonpath · PyPI, But now this introduces a subtle problem: in order to load the test modules from the tests directory, pytest prepends the root of the repository to  My problem is that when I run py.test the test fails because it can't find A.txt. I found out that it is because pytest uses the path Main\Test when running the test instead of changing the path to Main\Tests\A_test (I'm using relative path when opening A.txt inside the test file)

Python code coverage, Testing Python in Visual Studio Code including the Test Explorer. a test framework is not installed. With pytest, failed tests also appear in the Problems panel. Use a full path if pytest is located outside the current environment. pytestArgs  pytest determines a rootdir for each test run which depends on the command line arguments (specified test files, paths) and on the existence of ini-files. The determined rootdir and ini-file are printed as part of the pytest header during startup.

Testing Python in Visual Studio Code, 25 pytest import mechanisms and sys.path/PYTHONPATH cases or serious problems with this functionality are discovered after it gets more  I think we should warn the user that the option must be a filename and not an existing directory, similar that what was done in #2080.. The check would have to reside somewhere in junitxml.py thought

Comments
  • Here is the way to fix it with setuptools.
  • Please check @hoefling answer and consider changing your accepted one, if SO allows after this long: much better!
  • when am i cding to a directory? i am running py.test from my root. unless I am mistaken and you mean as pytest walks through my folders
  • if it was a cd issue, wouldn't i hit it on mac as well?
  • Oh, I misread and thought it doesn't work from the tests directory. still the trick in suggestion 1 would work. I only use Linux so I can't explain the behavior on other OSes.
  • do you have an import like that on all your test.py files?
  • yes, but my directory structure is usually slightly different - I usually keep /src and /test under the root directory.
  • It requires to rewrite relative imports to absolute ones, if you have the code for running the application not on the level, where you execute the command from. For example: project/test/all-my-tests and project/src/app.py and because of that change, one needs to call the app.py indirectly using a __main__.py file in project/src, so that one can use the call python -m src. Pretty messy stuff as far as I can tell.
  • @Zelphir: Using absolute imports is a recommended practice. Habnabit's has a good article about packaging best practices: blog.habnab.it/blog/2013/07/21/python-packages-and-you, and PEP8 says that "implicit relative imports should never be used and have been removed in Python 3." See: python.org/dev/peps/pep-0008.
  • @Apteryx You mean "project-absolute" right? Because things like /home/user/dev/projectxyz/src ... would be really bad and not run on other machines in most cases. I think what I meant is, that I have to always write the whole project root to module path even if a module is in the same folder as the file run. I didn't know that this is considered best practice, so that's a useful bit of information, thanks. I agree with most of pep8, although it is still not perfect.
  • @Zelphir, yes, that's what I meant. I believe the term absolute imports in Python always refer to "project-absolute". See: python.org/dev/peps/pep-0328/#rationale-for-absolute-imports. In fact, I'm pretty sure you can't import from random, absolute paths locations, at least using the default "import" mechanism.
  • I have added __init__.py in tests, that solved the problem. Now I can use pytest
  • This does not work, simple as that. Try putting a file at the root directory, and then importing that from a test. Setting PYTHONPATH to root works fine, this hack does not help at all.