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