We use fixture finalization to clean up after a test finishes. It helps keep tests independent and tidy by removing temporary data or closing resources.
Fixture finalization (request.addfinalizer) in PyTest
def fixture_name(request): # setup code here def cleanup(): # cleanup code here request.addfinalizer(cleanup) return resource
The request parameter is a special pytest object that gives access to test context.
addfinalizer registers a function to run after the test using this fixture finishes.
import pytest @pytest.fixture def temp_file(request): filename = "temp.txt" with open(filename, "w") as f: f.write("hello") def cleanup(): import os os.remove(filename) request.addfinalizer(cleanup) return filename
addfinalizer.import pytest @pytest.fixture def resource(request): res = acquire_resource() def cleanup(): res.release() request.addfinalizer(cleanup) return res
This test uses a fixture that creates a list. After the test, the list is cleared by the finalizer. The print statements show the order of setup, test, and cleanup.
import pytest @pytest.fixture def sample_list(request): data = [1, 2, 3] print("Setup: Created list") def cleanup(): data.clear() print("Cleanup: Cleared list") request.addfinalizer(cleanup) return data def test_modify_list(sample_list): sample_list.append(4) assert sample_list == [1, 2, 3, 4] print("Test: List modified")
Finalizers run even if the test fails, ensuring cleanup always happens.
You can add multiple finalizers if you need to clean up several things.
Using yield in fixtures is an alternative to addfinalizer for cleanup.
Fixture finalization cleans up resources after tests to keep tests independent.
request.addfinalizer registers cleanup functions to run after tests.
Finalizers run no matter if tests pass or fail, ensuring proper cleanup.
Practice
request.addfinalizer in a pytest fixture?Solution
Step 1: Understand the role of
This method is used inside fixtures to add a function that will run after the test, regardless of test outcome.request.addfinalizerStep 2: Identify the purpose of finalizers
Finalizers clean up resources like files, connections, or data to keep tests independent and avoid side effects.Final Answer:
To register a cleanup function that runs after the test finishes -> Option AQuick Check:
Finalizer = cleanup function [OK]
- Confusing finalizers with test skipping
- Thinking finalizers run before tests
- Using finalizers to parametrize tests
request?Solution
Step 1: Recall the correct method call syntax
Theaddfinalizermethod expects a callable (function) without calling it immediately.Step 2: Analyze each option
request.addfinalizer(cleanup_function()) calls the function immediately, which is incorrect. request.addfinalizer(cleanup_function) passes the function reference correctly. Options C and D use invalid syntax.Final Answer:
request.addfinalizer(cleanup_function) -> Option BQuick Check:
Pass function, don't call it [OK]
- Calling the cleanup function immediately
- Assigning instead of calling addfinalizer
- Using wrong method names
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
Solution
Step 1: Trace the fixture and test execution order
Fixture runs first, printing 'Setup done'. Then test runs, printing 'Test got resource: 42'. After test finishes, finalizer runs printing 'Cleanup done'.Step 2: Match output order with options
Only Setup done\nTest got resource: 42\nCleanup done matches the order: setup, test, cleanup.Final Answer:
Setup done\nTest got resource: 42\nCleanup done -> Option DQuick Check:
Setup -> Test -> Cleanup order [OK]
- Assuming cleanup runs before test
- Mixing print order of setup and test
- Thinking finalizer runs during fixture setup
request.addfinalizer:
@pytest.fixture
def my_fixture(request):
def cleanup():
print('Cleaning up')
request.addfinalizer(cleanup())
return 'data'
Solution
Step 1: Check how cleanup is passed to addfinalizer
The code callscleanup()immediately, passing its result (None) instead of the function itself.Step 2: Understand correct usage
We must pass the function reference without parentheses toaddfinalizerso it runs after the test.Final Answer:
The cleanup function is called immediately instead of being passed -> Option CQuick Check:
Pass function, don't call it [OK]
- Calling cleanup instead of passing it
- Defining cleanup outside fixture unnecessarily
- Thinking addfinalizer is not a method
request.addfinalizer to close two resources after a test. Which code correctly ensures both cleanup functions run after the test?Solution
Step 1: Check how finalizers are registered
@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 callsrequest.addfinalizertwice, passing function references without calling them.Step 2: Identify errors in other options
@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 torequest.addfinalizerattribute, overwriting it (wrong).Final Answer:
Option A correctly registers both cleanup functions as finalizers -> Option AQuick Check:
Call addfinalizer twice with function references [OK]
- Calling cleanup functions immediately
- Overwriting addfinalizer instead of calling it
- Combining cleanup prints but calling immediately
Ready to prove it?
Pass the test and this pattern moves unknown
