Framework Mode - Fixture finalization (request.addfinalizer)
Folder Structure
project_root/ ├── tests/ │ ├── test_example.py │ └── conftest.py ├── src/ │ └── app_code.py └── pytest.ini
project_root/ ├── tests/ │ ├── test_example.py │ └── conftest.py ├── src/ │ └── app_code.py └── pytest.ini
conftest.py, provides setup and teardown using request.addfinalizer.tests/ folder use fixtures for setup and cleanup.src/ folder, tested by tests.pytest.ini for pytest settings and options.Use pytest.ini to configure pytest options like markers and test paths.
Fixtures can accept request object to register finalizers for cleanup after tests.
Example: In conftest.py, define a fixture that sets up a resource and uses request.addfinalizer to release it after test finishes.
Environment variables or command line options can be accessed in fixtures for flexible configuration.
pytest-html for detailed HTML reports.request.addfinalizer for teardown: It ensures cleanup code runs after each test using the fixture.Where in this folder structure would you add a new fixture that opens a database connection and ensures it closes after each test?
Answer: Add the fixture in conftest.py inside the tests/ folder, using request.addfinalizer to close the connection.
request.addfinalizer in a pytest fixture?request.addfinalizerrequest?addfinalizer method expects a callable (function) without calling it immediately.import pytest
def cleanup():
print('Cleanup done')
@pytest.fixture
def resource(request):
request.addfinalizer(cleanup)
print('Setup done')
return 42
def test_example(resource):
print(f'Test got resource: {resource}')
assert resource == 42
request.addfinalizer:
@pytest.fixture
def my_fixture(request):
def cleanup():
print('Cleaning up')
request.addfinalizer(cleanup())
return 'data'
cleanup() immediately, passing its result (None) instead of the function itself.addfinalizer so it runs after the test.request.addfinalizer to close two resources after a test. Which code correctly ensures both cleanup functions run after the test?@pytest.fixture
def multi_resource(request):
def cleanup1():
print('Close resource 1')
def cleanup2():
print('Close resource 2')
request.addfinalizer(cleanup1)
request.addfinalizer(cleanup2)
return 'resources' correctly calls request.addfinalizer twice, passing function references without calling them.@pytest.fixture
def multi_resource(request):
def cleanup():
print('Close resource 1')
print('Close resource 2')
request.addfinalizer(cleanup())
return 'resources' calls cleanup immediately (wrong). @pytest.fixture
def multi_resource(request):
def cleanup1():
print('Close resource 1')
def cleanup2():
print('Close resource 2')
request.addfinalizer(cleanup1())
request.addfinalizer(cleanup2())
return 'resources' calls cleanup1() and cleanup2() immediately (wrong). @pytest.fixture
def multi_resource(request):
def cleanup1():
print('Close resource 1')
def cleanup2():
print('Close resource 2')
request.addfinalizer = cleanup1
request.addfinalizer = cleanup2
return 'resources' assigns functions to request.addfinalizer attribute, overwriting it (wrong).Pass the test and this pattern moves unknown