Verify resource cleanup using pytest fixture finalizer
Preconditions (2)
✅ Expected Result: The test passes and the cleanup function is executed after the test, releasing the resource properly
import pytest class Resource: def __init__(self): self.active = False def open(self): self.active = True def close(self): self.active = False @pytest.fixture def resource_fixture(request): res = Resource() res.open() def cleanup(): res.close() print("Cleanup called: resource closed") request.addfinalizer(cleanup) return res def test_resource_usage(resource_fixture): # Assert resource is active during test assert resource_fixture.active is True # The cleanup will run after this test finishes
This code defines a Resource class to simulate a resource that can be opened and closed.
The resource_fixture fixture creates and opens the resource. It uses request.addfinalizer to register a cleanup function that closes the resource after the test finishes.
The test test_resource_usage uses the fixture and asserts the resource is active during the test.
After the test completes, pytest automatically calls the cleanup function to close the resource, ensuring proper cleanup.
Now add a second fixture that depends on the first fixture and also uses addfinalizer for cleanup
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