-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Description
Using fixtures for setup and teardown:
Difference between older addfinalizer approach and recommended approach with yield only.
Note: The old method described here does still work (as mentioned in the documentation note), but I wish to highlight the different behaviour and the usefulness of the old method before the old method is removed entirely.
Current recommendation as documented in the second note here https://docs.pytest.org/en/latest/fixture.html#fixture-finalization-executing-teardown-code. If this method (do not add finalizer) is used and the setup code raises an exception then the teardown code is not executed.
Old behaviour (no longer recommended), using request.addfinalizer:
If setup code (before yield) raises an exception then the teardown code (after yield) is executed as long as addfinalizer is before the setup code as below,
# Old method - always executes the teardown code, even when setup raises exception
@pytest.fixture(scope='function')
def setupTeardown(request):
def fin():
print "Function teardown"
request.addfinalizer(fin)
print "Function setup"
setupPassed = False
assert setupPassed, "Argh setup failed"
yield
Example output:
platform linux2 -- Python 2.7.6, pytest-3.1.2, py-1.4.34, pluggy-0.4.0
rootdir: /home/slea1/workspace/sessions, inifile:
collected 1 items
testcases/testDir2/test_cnet-3_pytest_Fixtures_bug.py
Function setup
E
Function teardown
========================================================== short test summary info ==========================================================
ERROR testcases/testDir2/test_cnet-3_pytest_Fixtures_bug.py::test_fixtureSetupFail
================================================================== ERRORS ===================================================================
__________________________________________________ ERROR at setup of test_fixtureSetupFail __________________________________________________
request = <SubRequest 'setupTeardown' for <Function 'test_fixtureSetupFail'>>
@pytest.fixture(scope='function')
def setupTeardown(request):
def fin():
print "\nFunction teardown"
request.addfinalizer(fin)
print "\nFunction setup"
setupPassed = False
> assert setupPassed, "Argh setup failed"
E AssertionError: Argh setup failed
E assert False
testcases/testDir2/test_cnet-3_pytest_Fixtures_bug.py:23: AssertionError
Notice that the teardown code "Function teardown" is executed after the exception is raised.
Recommended method in documentation (do not use addfinalizer)
If setup raises an exception the teardown code is not executed.
# New method - doesn't execute teardown if exception caught in setup
@pytest.fixture(scope='function')
def setupTeardown(request):
print "\nFunction setup"
setupPassed = False
assert setupPassed, "Argh setup failed"
yield
# This teardown doesn't execute if setup fails
print "\nFunction teardown"
Example output:
platform linux2 -- Python 2.7.6, pytest-3.1.2, py-1.4.34, pluggy-0.4.0
rootdir: /home/slea1/workspace/sessions, inifile:
collected 1 items
testcases/testDir2/test_cnet-3_pytest_Fixtures_bug.py
Function setup
E
========================================================== short test summary info ==========================================================
ERROR testcases/testDir2/test_cnet-3_pytest_Fixtures_bug.py::test_fixtureSetupFail
================================================================== ERRORS ===================================================================
__________________________________________________ ERROR at setup of test_fixtureSetupFail __________________________________________________
request = <SubRequest 'setupTeardown' for <Function 'test_fixtureSetupFail'>>
@pytest.fixture(scope='function')
def setupTeardown(request):
print "\nFunction setup"
setupPassed = False
> assert setupPassed, "Argh setup failed"
E AssertionError: Argh setup failed
E assert False
testcases/testDir2/test_cnet-3_pytest_Fixtures_bug.py:8: AssertionError
Notice that the "Function teardown" is not printed.
Test code used in the above examples:
# session_setupPass_teardownPass, module_setupPass_teardownPass, class_setupPass_teardownPass, setupPass_teardownPass
def test_fixtureSetupFail(setupTeardown):
print "Test function executing..."
print "Test function complete"
pip list
Package Version
------------ -------
asn1crypto 0.22.0
bcrypt 3.1.3
cffi 1.10.0
colored 1.3.5
config 0.3.9
cryptography 1.9
enum34 1.1.6
idna 2.5
ipaddress 1.0.18
paramiko 2.2.1
pip 9.0.1
py 1.4.34
pyasn1 0.2.3
pycparser 2.17
PyNaCl 1.1.2
pytest 3.1.2
scp 0.10.2
setuptools 36.0.1
six 1.10.0
wheel 0.29.0
python version: 2.7.6
Operating system: Kubuntu 14.04