How to get directory with test from fixture in conftest.py

George Shuklin
OpsOps
Published in
2 min readAug 31, 2021

When I put my fixtures into conftest.py (which is the preferable way to reuse fixtures within a project), I stumble on one minor issue, is that fixture can’t use __file__ anymore to find directory where file is present.

The normal way in Python to see ‘own’ directory is to use

os.path.dirname(__file__)

(It uses magic variable __file__ with the file name of the current module where code is run). Due to obvious reasons when fixture is moved from (e.g.) /foo/bar/tests_slow/test_slow.py into /foo/bar/conftest.py , the content of __file__ is changing.

Why one want to use this ‘magic’?

The key reason is to get files relative to the test file:

.
├── conftest.py
└── some_tests
├── data.json
└── test_some.py

I want to access data.json from the fixture. When fixture is in the test_some, I just do os.path.join(os.path.dirname(__file__), "data.json") . It’s breaks if a fixture is moved to conftest.py .

Solution

With a bit of digging I found where to find the original path to the test file calling the fixture.

There is a magical fixture request (not the requests library! It’s a bit of collision here), which contains all information about the current test and fixture construction. And it has ‘module’, which is module with the test. And that module has own __file__ magic variable, which is the desired information.

Therefore, the content for fixture fixture1 inside conftest.py is:

@pytest.fixture()
def fixture1(request):
test_dir = os.path.dirname(request.module.__file__)
data_filename = os.path.join(test_dir, "data.json")
with open(data_filename, "r") as f:
return json.load(f)

If you have chain of fixtures, it’s ok to mix-in request at any point:

@pytest.fixture()
def complicated_fixture(fixture1, fixture2, fixture2, request):
...

Side note: you can pass request as a fixture into you test, but it’s a bit too much of introspection for my taste.

Update: if you ever decide to go by pytest_generate_tests way, it’s there too:

metafunc.module.__file__

--

--

George Shuklin
OpsOps

I work at Servers.com, most of my stories are about Ansible, Ceph, Python, Openstack and Linux. My hobby is Rust.