Fixtures

What is the fixture?

  • Such as setUp() and teardown() methods, “getting ready for” and “cleaning up after”
  • the code above the yield as “setup” and the code after yield as “teardown.”
  • Fixtures are used to feed some data to the tests such as database connections, URLs to test and some sort of input data.
  • if you wanted a test to use a fixture, you put it in the parameter list. But for classes that’s better to use @pytest.mark.usefixtures('fixture1', 'fixture2').
    • test using a fixture due to usefixtures cannot use the fixture’s return value
  • pytest --setup-show test_add.py -k valid_id ← to see what setup and teardown methods were being used
    • F’s and S’s for function and session scope
  • autouse=True as fixture argument, it runs all of the time for all functions
  • @pytest.fixture(autouse=True, scope='class/module/session', params=[], ids=[])

Built-in fixtures

  • tmpdir, request, pytestconfig

How to create a fixture?

  • SetUp and TearDown function
  • @pytest.fixture(autouse=True)
    def initialized_tasks_db(tmpdir):
        """Connect to db before testing, disconnect after."""
        # Setup : start db
    		tasks.start_tasks_db(str(tmpdir), 'tiny') 
    
    		yield # this is where the testing happens
    
        # Teardown : stop db
        tasks.stop_tasks_db()
    @pytest.fixture()
    def my_fixture_func():
    	print('Hello')
    	yield 
    	print('World')
  • Data fixture → passing to argument list
  • import pytest
    @pytest.fixture() 
    def some_data():
        """Return answer to ultimate question."""
    		return 42
    
    def test_some_data(some_data):
    	"""Use fixture return value in a test.""" 
    	assert some_data == 42

How to use the fixture?

  • To use any built-in or user defined fixture we need to pass the fixture name as the argument to function
  • pytest will look in the module of the test for a fixture of that name. It will also look in conftest.py files if it doesn’t find it in this file.

Using Fixtures for Test Data

Using Multiple Fixtures

Fixtures Scope

Scope controls how often a fixture gets set up and torn down.

  • Can have values: function, class, module, or session
  • The default is function
image
@pytest.fixture(autouse=True, scope='session') 
def footer_session_scope():
   """Report the time at the end of a session."""
	yield
	now = time.time()
	print('--')
	print('finished : {}'.format(time.strftime('%d %b %X', time.localtime(now)))) 
	print('-----------------')

Renaming fixtures

import pytest

@pytest.fixture(name='lue')
def ultimate_answer_to_life_the_universe_and_everything():
    """Return ultimate answer."""
		return 42

def test_everything(lue): 
"""Use the shorter name.""" 
		assert lue == 42

Parametrizing Fixtures

better than @pytest.mark.parametrize('task', tasks_to_try)

image
  • With ids@pytest.fixture(params=tasks_to_try, ids=task_ids)
  • request.keywords

Use fixture as a parameter for another class

@pytest.fixture
def dir1_fixture():
    return '/dir1'

@pytest.fixture
def dir2_fixture():
    return '/dir2'

@pytest.fixture(params=['dir1_fixture', 'dir2_fixture'])
def dirname(request):
    return request.getfixturevalue(request.param)
@pytest.fixture(params=["123344", "45678"], ids=range(2))
def test_data(request):
    return {"a": request.param}

def test_me_too(test_data):
    print(test_data)

Fixtures is used in mark.parametrize and which get the parameters, indirect=True

import pytest

@pytest.fixture
def fixture_name(request):
    return request.param

@pytest.mark.parametrize('fixture_name', ['foo', 'bar'], indirect=True)
def test_indirect(fixture_name):
    assert fixture_name == 'baz'


# indirect=True ensures you still execute the fixture body when you use parametrize on a test.
# similar to @pytest.fixture(params=[..]_

Create fixture inside a class

or even

Fixture to a class is applied to each test

@pytest.fixture
def a():
    print("A")


@pytest.fixture
def b():
    print("B")


@pytest.mark.usefixtures('b')
@pytest.mark.usefixtures('a')
class TestMe:
    def test_me(self):
        print("ME")

    def test_him(self):
        print("HIM")
SuperMade with Super