Bird
Raised Fist0
PyTesttesting~20 mins

Fixture finalization (request.addfinalizer) in PyTest - Practice Problems & Coding Challenges

Choose your learning style10 modes available
Challenge - 5 Problems
🎖️
Fixture Finalizer Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
❓ Predict Output
intermediate
2:00remaining
Understanding fixture finalization order with request.addfinalizer

What will be the output order of the print statements when running this pytest test?

PyTest
import pytest

def test_example(request):
    print("Start test")
    request.addfinalizer(lambda: print("First finalizer"))
    request.addfinalizer(lambda: print("Second finalizer"))
    print("End test")
AStart test\nEnd test\nFirst finalizer\nSecond finalizer
BFirst finalizer\nSecond finalizer\nStart test\nEnd test
CStart test\nEnd test\nSecond finalizer\nFirst finalizer
DStart test\nFirst finalizer\nEnd test\nSecond finalizer
Attempts:
2 left
💡 Hint

Remember that finalizers added later run first.

❓ assertion
intermediate
2:00remaining
Correct assertion to verify finalizer execution

You want to test that a finalizer function was called after the test. Which assertion correctly verifies this?

PyTest
import pytest

called = []

def test_finalizer_called(request):
    def cleanup():
        called.append(True)
    request.addfinalizer(cleanup)
    assert ???
Acalled == []
Bcalled == [True]
Ccalled is None
Dcalled == [False]
Attempts:
2 left
💡 Hint

Finalizers run after the test function finishes.

🔧 Debug
advanced
2:00remaining
Identify the error in fixture finalizer usage

What error will this pytest fixture cause?

PyTest
import pytest

@pytest.fixture
def resource(request):
    print("Setup resource")
    request.addfinalizer("cleanup")
    return "resource"
ANo error, runs fine
BTypeError: 'str' object is not callable
CNameError: name 'cleanup' is not defined
DSyntaxError: invalid syntax
Attempts:
2 left
💡 Hint

Check what type addfinalizer expects as argument.

🧠 Conceptual
advanced
2:00remaining
Why use request.addfinalizer instead of yield in fixtures?

Which reason best explains when to prefer request.addfinalizer over yield in pytest fixtures?

AWhen you need multiple finalizers to run in a specific order
BWhen the fixture does not require any cleanup
CWhen you want to skip the test conditionally
DWhen you want to run cleanup code before the test starts
Attempts:
2 left
💡 Hint

Think about multiple cleanup steps and their order.

❓ framework
expert
3:00remaining
Predict the final output of nested finalizers in pytest

Given this pytest test, what is the exact printed output?

PyTest
import pytest

def test_nested_finalizers(request):
    print("Test start")
    def first_cleanup():
        print("First cleanup start")
        def second_cleanup():
            print("Second cleanup")
        request.addfinalizer(second_cleanup)
        print("First cleanup end")
    request.addfinalizer(first_cleanup)
    print("Test end")
ATest start\nTest end\nFirst cleanup end\nFirst cleanup start\nSecond cleanup
BTest start\nTest end\nFirst cleanup start\nSecond cleanup\nFirst cleanup end
CTest start\nTest end\nSecond cleanup\nFirst cleanup start\nFirst cleanup end
DTest start\nTest end\nFirst cleanup start\nFirst cleanup end\nSecond cleanup
Attempts:
2 left
💡 Hint

Remember that finalizers run after the test, and added finalizers run in reverse order.

Practice

(1/5)
1. What is the main purpose of using request.addfinalizer in a pytest fixture?
easy
A. To register a cleanup function that runs after the test finishes
B. To skip the test if a condition is met
C. To mark a test as expected to fail
D. To parametrize the test with multiple inputs

Solution

  1. Step 1: Understand the role of request.addfinalizer

    This method is used inside fixtures to add a function that will run after the test, regardless of test outcome.
  2. Step 2: Identify the purpose of finalizers

    Finalizers clean up resources like files, connections, or data to keep tests independent and avoid side effects.
  3. Final Answer:

    To register a cleanup function that runs after the test finishes -> Option A
  4. Quick Check:

    Finalizer = cleanup function [OK]
Hint: Finalizers always clean up after tests finish [OK]
Common Mistakes:
  • Confusing finalizers with test skipping
  • Thinking finalizers run before tests
  • Using finalizers to parametrize tests
2. Which of the following is the correct syntax to add a finalizer inside a pytest fixture using request?
easy
A. request.addfinalizer(cleanup_function())
B. request.addfinalizer(cleanup_function)
C. request.addfinalizer = cleanup_function
D. request.finalizer(cleanup_function)

Solution

  1. Step 1: Recall the correct method call syntax

    The addfinalizer method expects a callable (function) without calling it immediately.
  2. 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.
  3. Final Answer:

    request.addfinalizer(cleanup_function) -> Option B
  4. Quick Check:

    Pass function, don't call it [OK]
Hint: Pass function name without parentheses to addfinalizer [OK]
Common Mistakes:
  • Calling the cleanup function immediately
  • Assigning instead of calling addfinalizer
  • Using wrong method names
3. What will be the output when running this pytest code snippet?
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
medium
A. Cleanup done\nSetup done\nTest got resource: 42
B. Setup done\nCleanup done\nTest got resource: 42
C. Test got resource: 42\nSetup done\nCleanup done
D. Setup done\nTest got resource: 42\nCleanup done

Solution

  1. 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'.
  2. Step 2: Match output order with options

    Only Setup done\nTest got resource: 42\nCleanup done matches the order: setup, test, cleanup.
  3. Final Answer:

    Setup done\nTest got resource: 42\nCleanup done -> Option D
  4. Quick Check:

    Setup -> Test -> Cleanup order [OK]
Hint: Finalizer runs after test, not before or during [OK]
Common Mistakes:
  • Assuming cleanup runs before test
  • Mixing print order of setup and test
  • Thinking finalizer runs during fixture setup
4. Identify the error in this pytest fixture code that uses request.addfinalizer:
@pytest.fixture
def my_fixture(request):
    def cleanup():
        print('Cleaning up')
    request.addfinalizer(cleanup())
    return 'data'
medium
A. The cleanup function must be defined outside the fixture
B. The fixture should not return any value
C. The cleanup function is called immediately instead of being passed
D. The addfinalizer method does not exist on request

Solution

  1. Step 1: Check how cleanup is passed to addfinalizer

    The code calls cleanup() immediately, passing its result (None) instead of the function itself.
  2. Step 2: Understand correct usage

    We must pass the function reference without parentheses to addfinalizer so it runs after the test.
  3. Final Answer:

    The cleanup function is called immediately instead of being passed -> Option C
  4. Quick Check:

    Pass function, don't call it [OK]
Hint: Don't add parentheses when passing cleanup to addfinalizer [OK]
Common Mistakes:
  • Calling cleanup instead of passing it
  • Defining cleanup outside fixture unnecessarily
  • Thinking addfinalizer is not a method
5. You want to use request.addfinalizer to close two resources after a test. Which code correctly ensures both cleanup functions run after the test?
hard
A.
@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'
B.
@pytest.fixture
def multi_resource(request):
    def cleanup():
        print('Close resource 1')
        print('Close resource 2')
    request.addfinalizer(cleanup())
    return 'resources'
C.
@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'
D.
@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'

Solution

  1. 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 calls request.addfinalizer twice, passing function references without calling them.
  2. 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 to request.addfinalizer attribute, overwriting it (wrong).
  3. Final Answer:

    Option A correctly registers both cleanup functions as finalizers -> Option A
  4. Quick Check:

    Call addfinalizer twice with function references [OK]
Hint: Call addfinalizer separately for each cleanup function [OK]
Common Mistakes:
  • Calling cleanup functions immediately
  • Overwriting addfinalizer instead of calling it
  • Combining cleanup prints but calling immediately
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard