pytest fixtures
Once you start writing many tests – more than you wrote in Lent1A, you’ll find that setting up the context in which to run each test can take a while. pytest’s fixtures are a way to ease the effort of writing the set-up code, and to make the running of the tests faster by using caching. Here’s some code adapted from pythontesting.net to demonstrate some features.
import pytest
@pytest.fixture(scope='module')
def resource_a_setup(request):
'''Creating resource a, shared across a module'''
print('\nSetting up resources a')
def resource_a_teardown():
print('\nTearing down resources a')
request.addfinalizer(resource_a_teardown)
@pytest.fixture(scope='function')
def resource_b_setup(request):
'''Create resource b, not shared'''
print('\nSetting up resources b')
def resource_b_teardown():
print('\nTearing down resources b')
request.addfinalizer(resource_b_teardown)
def test_1(resource_a_setup, resource_b_setup):
print('\ntest_1 - needs resource a and b')
def test_2():
print('\ntest_2 - does not need resource a or b')
def test_3(resource_a_setup, resource_b_setup):
print('\ntest_3 - needs_resource a and b')
Put this code into (say) test_fixturedemo.py and run
pytest -v -s
Note how the resources are created and destroyed. Use
pytest --fixtures
to get a list of fixtures (including build-in ones)
Using your own exceptions with pytest
Try this (adapted from stackoverflow)
class CustomError(Exception):
pass
def foo():
raise ValueError('everything is broken')
def bar():
raise CustomError('still broken')
import pytest
def test_fooErrorHandling():
with pytest.raises(ValueError) as excinfo:
foo()
assert str(excinfo.value) == 'everything is broken'
def test_barSimpleErrorHandling():
# don't care about the specific message
with pytest.raises(CustomError):
bar()
def test_barSpecificErrorHandling():
# check the specific error message
with pytest.raises(CustomError) as excinfo:
bar()
assert str(excinfo.value) == 'still broken'
def test_barWithoutImportingExceptionClass():
# if for some reason you can't import the specific exception class,
# catch it as generic and verify it's in the str(excinfo)
with pytest.raises(Exception) as excinfo:
bar()
assert 'CustomError:' in str(excinfo)
parametrize
If you’re doing many tests where only the parameters vary, you can use
parametrize.
Here’s an example from the pytest documention which does 3 tests at once –
import pytest
@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
def test_eval(test_input, expected):
assert eval(test_input) == expected
Computing help and support