How to Avoid Repeated Instantiation of a Class in Each Pytest Unit Test

The aim of this page📝 is to share how using @pytest.fixture decorator can help avoid the repetition of class instantiation in Pytest tests. I find it syntactically a bit cumbersome as you access your class through a decorated function, but it's still useful.

Pavol Kutaj
2 min readSep 14, 2023
import pytest
import example_module

#ExampleClass defined in example_module

@pytest.fixture
def client():
return example_module.ExampleClass(TEST_CLIENT_TAG, TEST_TICKET_ID)

def test_class_contains_expected_data(client):
assert client.client_tag == "com_foobar"
assert client.org_id == "bbc19d7f-b45b-4dad-b9bd-34a818f23241"
assert client.ticket_id == "EXAMPLE-1234"
assert client.dev_server == "com-foobar-dev1.net"
assert client.prod_server == "com-foobar-prod1.net"

def test_read_keys_returns_dict_with_dev_and_prod_readonly_keys(client, monkeypatch):
def mock_get_keys(_, __):
return {
"dev": "123456789",
"prod": "123456789"
}
monkeypatch.setattr(ExampleClass, "_get_keys", mock_get_keys)
assert client.read_only_keys == {
"dev": "123456789",
"prod": "123456789"
}
  • … and so on for the rest of the test functions
  • In this example, we define a client fixture that returns an instance of the class.
  • Then, we can pass this fixture as an argument to each test function that needs it.
  • This way, the ExampleClass class is only instantiated once and reused across all test functions.
  • In pytest, you can use fixtures to set up preconditions for your tests.
  • Fixtures are defined using the @pytest.fixture decorator and can take parameters.
  • Here’s a simpler example that demonstrates how to initialize a class with two arguments before running tests that check the values of its fields:
import pytest

class MyClass:
def __init__(self, name, age):
self.name = name
self.age = age

@pytest.fixture
def my_class():
return MyClass(name="pavol", age=39)

def test_name(my_class):
assert my_class.name == "pavol"

def test_age(my_class):
assert my_class.age == 39
  • Please note that the following, a more intuitive approach of “class fixtures” is not supported (maybe in the future, the error message says:)
""" DOES NOT WORK """
@pytest.fixture
class AccessConfig:
def __init__(self):
self.client_name = "com_snowplowanalytics"
self.env = "prod1"

# > ..\..\..\..# \AppData\Local\Programs\Python\Python311\Lib\site-packages\_pytest\fixtures.# py:1195: in __call__
# raise ValueError("class fixtures not supported (maybe in the future)")
# E ValueError: class fixtures not supported (maybe in the future)

--

--

No responses yet