I would like to understand what is the differance between running:
$ pytest
and
$ python -m pytest tests
I am worikng in a virtual enviroment on a Mac. The first solution gives me an error :
ModuleNotFoundError: No module named 'app'
The second solution works fine.
Why does the second solution work and the the first one not?
How can I make it work with just $ pytest?
My folder structure:
├── app.py
├── requirements.txt
├── templates
├── tests
│ ├── conftest.py
│ ├── functional
│ │ ├── __init__.py
│ │ └── test_s.py
│ └── unit
│ ├── __init__.py
│ └── test_app.py
└── venv
In test_app.py, this line fails:
from app import app
python -m pytest adds the current directory to sys.path, i.e. lets you import modules from there.
This is a hint that there is something - let's call it - not optimal with your directory structure.
Why this may not be a good thing, you can read in this fantastic blog post
https://blog.ganssle.io/articles/2019/08/test-as-installed.html
I also wrote a short blog post about this topic:
https://jugmac00.github.io/til/what-is-the-difference-between-invoking-pytest-and-python-m-pytest/
The difference is comming from the Python algorithm of searching modules, but also the way how Pytest discovers tests.
1. Python module searching
It is done according to Python implementation as following:
It can be quite complicated. I see this nicely explained "in extended mode" here: Where is Python's sys.path initialized from?
2. Pytest discovery mechanism
So
from app import app
when you are importing 'app' like above it will be searched in diffirent way in both cases. In the other words 'current dir' in sys.path is set diffirently for both cases. You can check this by printing sys.path list.
It is not issue, but the way how python/pytest works.
3. Example of workaround
You can workaround this by for example by something like below (I am putting this to separate pathmagic.py file and importing later pathmagic in test_xyz )
import pathmagic # noqa Pep8 uncheck
pathmagic.py
import sys
import os
sys.path.append(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
sys.path.append(os.path.dirname((os.path.dirname(os.path.dirname(os.path.realpath(__file__))))))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With