Fixtures hold setup code

Fixtures are a way to separate some code that we want to run before or after a test and put it in a different function than the test function itself.

Let’s say we have a couple of tests with common setup code:

def test_1():
    # setup code running before the test
    print('\nbefore each test')
    # actual test code
    print('test_1()')

def test_2():
    # setup code running before the test
    print('\nbefore each test')
    # actual test code
    print('test_2()')

We could use xunit fixtures, but we’re not going to

If we want to use xunit fixtures, we could create a setup function like:

def setup_function(function):
    print('\nbefore each test')

That would work, but it’s way less powerful than native pytest fixtures.

Defining a pytest fixture

Instead of using xunit style, let’s use native pytest fixtures and do this:

import pytest

@pytest.fixture()
def before():
    print('\nbefore each test')

def test_1(before):
    print('test_1()')

def test_2(before):
    print('test_2()')

That before() function above is “the fixture” or “the fixture function”.

Note a few import parts:

  • We need to import pytest.
  • The @pytest.fixture() decorator is what makes the function being decorated a fixture.
  • Tests using it name the fixture as one of their parameters. In this case before.
  • The actual name doesn’t matter. However, I find it boring to call fixtures “setup()”.
  • Like any other function, a meaningful name is usually a good choice.
  • Since fixtures often represent a resource or some data, calling the function a name that reflects the resource or data is a good idea.

Benefits of fixtures

This has many benefits:

  • The test code is cleaner.
  • If the setup code needs to change, we change it in one place.
  • We get to decide which tests need the setup code.

And so much more

There’s a lot we can do with fixtures.
And that’s really the content of the rest of this series.