Skip to content

Fixtures

Fixtures in PyTest is a way to prepare data for tests and clean up after them.

Take a look at this code:

import pytest


@pytest.fixture()
def my_fixture():
    print("\n I'm the fixture - setUp")
    yield
    print("I'm the fixture - tearDown")


def test_first(my_fixture):
    print("I'm the first test")

Its effect is:

I'm the fixture - setUp

PASSED                                           [100%]I'm the first test

I'm the fixture - tearDown

Which means that with the decorator * Pytest.fixture *, we mark the function that will be fixtures. The word yield separates the code that is used to prepare the environment for testing (setUp) from the code that is used to clean up after the test (tearDown).

The applied fixtures for the test are simply passed in a parameter.

Suppose we have such a class:

class Data:
    def __init__(self):
        self.name = None
        self.info = None

    def prepare(self, name, info):
        self.name = name
        self.info = info

Tests using fixtures could look like this:

import pytest
from ex6 import Data


@pytest.fixture()
def prepared_object():
    data = Data()
    data.prepare("John", "Smith")
    yield data
    data.prepare("John", "Smith")


def test_first(prepared_object: Data):
    assert prepared_object.name == "John"
    prepared_object.prepare("John", "Test")
    assert prepared_object.info == "Test"


def test_second(prepared_object: Data):
    assert prepared_object.name == "John"
    prepared_object.prepare("Test", "Test")
    assert prepared_object.info == "Test"
    assert prepared_object.name == "Test"

in this case they build the baseline for the tests.

Fixtures usually prepare some objects that depend on the tested objects, e.g. some more complex mocks.

If we group the tests into a class, we can do it like this:

from unittest import TestCase
from ex6 import Data


class Test(TestCase):

    def setUp(self):
        self.data = Data()
        self.data.prepare("John", "Smith")

    def test_first(self):
        assert self.data.name == "John"
        self.data.prepare("John", "Test")
        assert self.data.info == "Test"

    def test_second(self):
        assert self.data.name == "John"
        self.data.prepare("Test", "Test")
        assert self.data.info == "Test"
        assert self.data.name == "Test"

    def tearDown(self):
        self.data.prepare("John", "Smith")

that is, we define the * setUp * and * tearDown * methods, which is the appropriate question fixture.