What if your tests could clean up after themselves perfectly every time, without you lifting a finger?
Why Fixture finalization (request.addfinalizer) in PyTest? - Purpose & Use Cases
Imagine you run tests that create temporary files or open database connections. After each test, you have to manually delete files or close connections by writing cleanup code everywhere.
This manual cleanup is slow and easy to forget. If you miss cleaning up, leftover files or open connections cause errors in later tests. It's like leaving your kitchen messy after cooking--next time you cook, it's harder and risky.
Using request.addfinalizer in pytest fixtures lets you register cleanup code that runs automatically after the test finishes. This keeps your tests clean and safe without repeating cleanup code everywhere.
def test_example(): resource = open_resource() # test steps resource.close() # manual cleanup
import pytest @pytest.fixture def resource(request): res = open_resource() request.addfinalizer(res.close) return res def test_example(resource): # test steps using resource pass
It enables reliable, automatic cleanup after tests, so your test environment stays fresh and tests don't interfere with each other.
Think of testing a web app that creates temporary user accounts. Using request.addfinalizer, you can automatically delete these accounts after each test, avoiding clutter and conflicts.
Manual cleanup is error-prone and repetitive.
request.addfinalizer automates cleanup after tests.
This keeps tests independent and environment clean.
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
