I'm attempting to use pytest to automate my test process. I have several files' worth of test cases (test_methodA.py
, test_methodB.py
, etc.) in a folder called test
, which is itself in the top-level directory of my project. These tests are all running on a program contained in a single file - program.py
. This program.py
file is also in the top-level directory, as is a folder's worth of configuration files confs
that it needs to function properly.
When I run pytest from the top-level directory with an argument of one of my test files:
$ pytest test/test_methodA.py
the program runs properly and passes the tests. However, if I just run pytest without arguments:
$ pytest
all of my tests fail because my program's initialization methods throw a FileNotFoundError
when trying to access configuration files.
I've experimented with this behavior, and determined that the direct cause is pytest using the incorrect working directory (the directory one level above the project's top-level directory). For example, if I do
$ cd test
$ pytest
all of the tests work correctly. I've also confirmed this by having one of the tests print os.getcwd()
to the console.
No directories involved in the project contain an __init__.py
file, which most of the search results I found for this issue are focused on. What other causes would there be for this issue?
Your issue is using relative paths when opening the files:
open('file/path.yml', 'r')
will resolve the path to the directory you're executing the code from. This means when running program.py
from another directory will result in a FileNotFoundError
because the script will look for the config files in the wrong dir. You can easily test that by changing the dir and trying to run the script:
$ cd /tmp
$ python /path/to/program.py
Traceback (most recent call last):
File "/path/to/program.py", line 1, in <module>
with open('file/path.yaml') as f:
FileNotFoundError: [Errno 2] No such file or directory: 'file/path.yaml'
You can fix that by building the paths relative to the program.py
script (__file__
is the name of the python file being executed):
import os
parent_dir = os.path.dirname(__file__)
file = os.path.join(parent_dir, 'file', 'path.yaml')
with open(file, 'r') as fp:
...
If you use Python 3.4 or newer, the path resolution is more elegant by using pathlib
:
# program.py
import pathlib
parent_dir = pathlib.Path(__file__).parent
file = parent_dir / 'file' / 'path.yaml'
with file.open('r') as fp:
...
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