I’m going to cover the syntax for pytest support for xUnit style fixtures.
Then I’ll give a more reasonable and typical example, using just one set of fixture functions.
And then address the issue of having tests mixed in a file. Some that need the resource, and some that don’t.

Depending on what scope you want your fixtures, you define setup/teardown pairs.

  • Module (setup_module/teardown_module)
    • Sets things up once for the module, teardown after everything.
  • Function (setup_function/teardown_function)
    • Wraps every test function with calls.
    • Gets called multiple times, once for each function
  • Class (setup_class/teardown_class)
    • Like module level, but for classes, once for a class.
  • Method (setup_method/teardown_method)
    • Like function level, but for classes.
    • Gets called multiple times, once for each test method in a class

Example using module, function, class, and method fixtures

from __future__ import print_function

def setup_module(module):
    print('\nsetup_module()')

def teardown_module(module):
    print('teardown_module()')

def setup_function(function):
    print('\nsetup_function()')

def teardown_function(function):
    print('\nteardown_function()')

def test_1():
    print('-  test_1()')

def test_2():
    print('-  test_2()')


class TestClass:

    @classmethod 
    def setup_class(cls):
        print ('\nsetup_class()')
 
    @classmethod 
    def teardown_class(cls):
        print ('teardown_class()')
 
    def setup_method(self, method):
        print ('\nsetup_method()')
 
    def teardown_method(self, method):
        print ('\nteardown_method()')

    def test_3(self):
        print('- test_3()')

    def test_4(self):
        print('- test_4()')

And lets run it to see the flow. I did remove some of the extra blank lines for this post.

$ py.test -s -v test_xunit_style_fixtures.py
================================ test session starts ================================
platform darwin -- Python 2.7.5 -- pytest-2.3.4 -- /usr/bin/python
collected 4 items 

test_xunit_style_fixtures.py:17: test_1 
setup_module()
setup_function()
-  test_1()
PASSED
teardown_function()

test_xunit_style_fixtures.py:20: test_2 
setup_function()
-  test_2()
PASSED
teardown_function()

test_xunit_style_fixtures.py:40: TestClass.test_3 
setup_class()
setup_method()
- test_3()
PASSED
teardown_method()

test_xunit_style_fixtures.py:43: TestClass.test_4 
setup_method()
- test_4()
PASSED
teardown_method()
teardown_class()
teardown_module()


============================= 4 passed in 0.01 seconds ==============================

Realistic example

Typically, you don’t throw all of the fixture types together.
Most of the time, one style is enough, depending what you are setting up, initializing, etc. and if it needs re-initialized before every test, and cleaned up after every test.

So, lets make things a bit simpler.

I’ve got a resource, called resource_a. I know, boring name. It’s just something that needs a setup and a teardown function.

This really could be any sort of resource:

  • temp file
  • temp directory
  • database connection
  • db transaction that needs rolled back after testing
  • open socket connection
  • a signal generator putting out a test signal
  • you get the drift

In this example, I’ve used method level fixtures so the setup/teardown happens at the beginning and end of the module, once for all the tests. Maybe it’s an expensive operation or something.

Here’s our simpler example with a resource.

from __future__ import print_function

def resource_a_setup():
    print('resources_a_setup()')

def resource_a_teardown():
    print('resources_a_teardown()')

def setup_module(module):
    print('\nsetup_module()')
    resource_a_setup()

def teardown_module(module):
    print('\nteardown_module()')
    resource_a_teardown()

def test_1_that_needs_resource_a():
    print('test_1_that_needs_resource_a()')

And the output. ``` $ py.test -s -v test_realistic_one_func.py ================================ test session starts ================================ platform darwin – Python 2.7.5 – pytest-2.3.4 – /usr/bin/python collected 1 items

test_realistic_one_func.py:17: test_1_that_needs_resource_a setup_module() resources_a_setup() test_1_that_needs_resource_a() PASSED teardown_module() resources_a_teardown()

============================= 1 passed in 0.01 seconds ==============================


### Adding another test function {#adding-another-test-function}

Then we add a test that actually doesn’t need the resource: ```
# ...
def test_2_that_does_not():
    print('\ntest_2_that_does_not()')

And we re-run it. ``` $ py.test -s -v test_realistic_two_funcs.py ================================ test session starts ================================ platform darwin – Python 2.7.5 – pytest-2.3.4 – /usr/bin/python collected 2 items

test_realistic_two_funcs.py:17: test_1_that_needs_resource_a setup_module() resources_a_setup() test_1_that_needs_resource_a() PASSED test_realistic_two_funcs.py:20: test_2_that_does_not test_2_that_does_not() PASSED teardown_module() resources_a_teardown()

============================= 2 passed in 0.01 seconds ==============================


This isn’t really a problem so far.  
Since the first test needs the resource, it’s fine the way we are doing things.

## Problem: the resource is set up even when we don’t need it. {#problem-the-resource-is-set-up-even-when-we-dont-need-it.}

If we just want to run one function, the second one, that doesn’t need the resource, the fixture is run anyway.

$ py.test -s -v test_realistic_two_funcs.py::test_2_that_does_not ================================ test session starts ================================ platform darwin – Python 2.7.5 – pytest-2.3.4 – /usr/bin/python collected 3 items

test_realistic_two_funcs.py:20: test_2_that_does_not setup_module() resources_a_setup() test_2_that_does_not() PASSED teardown_module() resources_a_teardown()

============================= 1 passed in 0.01 seconds ==============================


This is a waste.  
If the fixtures are quite lengthy, it can seriously slow down the test run unnecessarily.

## Creating classes to separate fixture needs {#creating-classes-to-separate-fixture-needs}

You can relatively cleanly deal with this by either isolating tests requiring a resource to their own module, or to their own class.

I’ll demonstrate the class solution to this problem.

Move the fixtures from module to class level, and move the tests that use the resource into the class.

from future import print_function

def resource_a_setup(): print(‘resources_a_setup()')

def resource_a_teardown(): print(‘resources_a_teardown()')

class TestClass:

@classmethod 
def setup_class(cls):
    print ('\nsetup_class()')
    resource_a_setup()

@classmethod 
def teardown_class(cls):
    print ('\nteardown_class()')
    resource_a_teardown()

def test_1_that_needs_resource_a(self):
    print('\ntest_1_that_needs_resource_a()')

def test_2_that_does_not(): print('\ntest_2_that_does_not()')


Now we can run the test in isolation without expensive and unnecessary resource setup/cleanup.

$ py.test -s -v test_separation_of_fixtures.py::test_2_that_does_not ================================ test session starts ================================ platform darwin – Python 2.7.5 – pytest-2.3.4 – /usr/bin/python collected 2 items

test_separation_of_fixtures.py:25: test_2_that_does_not test_2_that_does_not() PASSED

============================= 1 passed in 0.01 seconds ==============================


And the resource is still dealt with correctly when we do need it.

$ py.test -s -v test_separation_of_fixtures.py ================================ test session starts ================================ platform darwin – Python 2.7.5 – pytest-2.3.4 – /usr/bin/python collected 2 items

test_separation_of_fixtures.py:21: TestClass.test_1_that_needs_resource_a setup_class() resources_a_setup()

test_1_that_needs_resource_a() PASSED teardown_class() resources_a_teardown()

test_separation_of_fixtures.py:25: test_2_that_does_not test_2_that_does_not() PASSED

============================= 2 passed in 0.01 seconds ==============================


For lots and lots of circumstances, resource handling in this manner is completely sufficient.

However, I do believe that the pytest fixture mechanism (which I’ll cover in my next post), is a more elegant and scalable solution to the problem.