eolas/zk/Pytest_fixtures.md
2026-01-11 18:27:51 +00:00

2.2 KiB

tags
python
pytest

Fixtures are a way to provide data or state to your tests. Typically, although not exclusively, for processes that you want to reuse accross different test_ functions. They are defined at the "arrange" stage of testing.

Example: testing class methods under test

class Person:
   def __init__(self, name):
        self.name = name

   def print_name(self):
    return f"Your name is {self.name}"

To create a fixture of this class:

@pytest.fixture
def my_person():
    person = new Person('Thomas')
    return person.name()

test_print_name(my_person):
    assert(my_person) == 'Thomas'

Note we define our fixture and then inject it into our test function. Functions request fixtures they require by declaring them as arguments.

Alternatively you could just return the class from the fixture and test the methods individually within the test function.

Integrating with @patch to provide mock fixtures

Say we wanted to mock reading a JSON file.

We could create a fixture:


@pytest fixture
def raw_json():
    return json.dumps({"key": "value"})

And pass it in to the mock of the global open method:

from unittest.mock import mock_open, patch

def test_json_parsing(raw_json):
    with patch("builtins.open", mock_open(read_data=raw_json))
        # Then assert etc

This fixture could then be re-used to test any other method that relies on incoming JSON from a file.

Example: setup and teardown - before each and after each

Fixtures can be leveraged to setup 'before each...' and 'after each...' logic:

@pytest.fixture(scope="function")
def setup():
    os.environ["POCKET_LAMBDA_ENDPOINT"] = "https://some_endpoint.com/{article_type}"
    yield
    del os.environ["POCKET_LAMBDA_ENDPOINT"]

Here yield is a placeholder for the tests that run in between the setup and teardown.

We use scope="function" to signal that this will run before/after any tests that inject the fixture.

Then to specify the units that will run as the yield we just inject setup:

def some_function(setup_function):
    pass

Example: setting up mocks before every test

We can combine the