Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pytest without arguments has wrong working directory

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?

like image 734
Green Cloak Guy Avatar asked Sep 20 '25 11:09

Green Cloak Guy


1 Answers

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:
    ...
like image 166
hoefling Avatar answered Sep 23 '25 00:09

hoefling