Reputation: 653
I have a set of fixtures that all do the same thing, open up a json file and make it available to a test class.
@pytest.fixture(scope="class")
def category_params(request):
base_path = os.path.abspath(..)
path = os.path.join(base_path, "data/category_params.json")
with open(path, "r") as fp:
category_params = json.load(f)
return category_params
I repeat this set up for all of my different test categories in the test domain. It seems like something that I ought to be writing a single function for, but I am unsure as to how to use pytest to accomplish that. I believe I should be asking how to make a fixture factory, that is a pytest fixture object that makes other fixture objects.
Upvotes: 2
Views: 2246
Reputation: 40884
(Warning: I did not test this code.)
I think something like this should work.
def make_fixture_for(data_file):
@pytest.fixture(scope="class")
def params_fixture(request):
base_path = os.path.abspath(..)
path = os.path.join(base_path, data_file)
with open(path, "r") as fp:
return json.load(fp)
return params_fixture
foo_params = make_fixture_for("data/foo.json")
bar_params = make_fixture_for("data/bar.json")
This defines fixture functions at the module's top level, where pytest
expects them,
but does so in a sort of compact way.
This can be done in one loop over data file names and some mucking with globals
to put them into the module's top-level context, but it would feel like impenetrable magic. The code above is very trivial.
Maybe pytest
would not like a lot of fixture functions having the same name internally; then setting .__name__
on function may help, or not; again, I did not test this code, and I don't remember the details of pytest
's fixture discovery process.
Upvotes: 1
Reputation: 8604
You can parametrize your fixture function which means that each test can give it a a different JSON file to load:
import pytest
import os
import json
@pytest.fixture(scope="class")
def json_content(request):
base_path = os.path.abspath(..)
path = os.path.join(base_path, request.param)
with open(path, "r") as fp:
data = json.load(fp)
return data
@pytest.mark.parametrize("json_content", ["abc.json"], indirect=True)
def test_a(json_content):
print(json_content)
@pytest.mark.parametrize("json_content", ["xyz.json"], indirect=True)
def test_b(json_content):
print(json_content)
Note: The test examples don't show use of the same fixture per class but that's not necessary to demonstrate the parametrization.
Upvotes: 3