Bird
Raised Fist0
PyTesttesting~10 mins

Shared expensive resource patterns in PyTest - Interactive Code Practice

Choose your learning style10 modes available

Start learning this pattern below

Jump into concepts and practice - no test required

or
Recommended
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Practice - 5 Tasks
Answer the questions below
1fill in blank
easy

Complete the code to define a fixture that runs once per module.

PyTest
import pytest

@pytest.fixture(scope=[1])
def expensive_resource():
    print("Setup expensive resource")
    yield
    print("Teardown expensive resource")
Drag options to blanks, or click blank then click option'
Afunction
Bmodule
Cclass
Dsession
Attempts:
3 left
💡 Hint
Common Mistakes
Using 'function' scope causes the fixture to run before every test, which is inefficient for expensive resources.
2fill in blank
medium

Complete the code to use the fixture in a test function.

PyTest
def test_example([1]):
    assert True
Drag options to blanks, or click blank then click option'
Aexpensive_resource
Bresource
Cfixture
Dsetup
Attempts:
3 left
💡 Hint
Common Mistakes
Using a different parameter name than the fixture name will not inject the fixture.
3fill in blank
hard

Fix the error in the fixture scope to share the resource across all tests in all modules.

PyTest
import pytest

@pytest.fixture(scope=[1])
def global_resource():
    print("Setup global resource")
    yield
    print("Teardown global resource")
Drag options to blanks, or click blank then click option'
Afunction
Bmodule
Csession
Dclass
Attempts:
3 left
💡 Hint
Common Mistakes
Using 'module' scope only shares the fixture within one module, not across modules.
4fill in blank
hard

Fill both blanks to create a fixture that sets up a database connection once per class and tears it down after all tests in the class.

PyTest
import pytest

@pytest.fixture(scope=[1])
def db_connection():
    print("Connect to DB")
    yield
    print("Disconnect from DB")

class TestDB:
    def test_query1(self, [2]):
        assert True
Drag options to blanks, or click blank then click option'
Aclass
Bdb_connection
Cmodule
Dfunction
Attempts:
3 left
💡 Hint
Common Mistakes
Using 'function' scope causes the fixture to run before every test method, not once per class.
5fill in blank
hard

Fill all three blanks to create a session-scoped fixture that returns a resource and is used in a test.

PyTest
import pytest

@pytest.fixture(scope=[1])
def shared_resource():
    resource = "Expensive Resource"
    yield resource
    print("Cleanup resource")

def test_use_resource([2]):
    assert [3] == "Expensive Resource"
Drag options to blanks, or click blank then click option'
Asession
Bshared_resource
Dmodule
Attempts:
3 left
💡 Hint
Common Mistakes
Using different names for the fixture parameter and assertion variable causes errors.

Practice

(1/5)
1. What is the main benefit of using a pytest fixture with a scope='module' when dealing with expensive resources?
easy
A. The fixture runs only once per test session, regardless of module.
B. The fixture setup runs once per module, reducing repeated expensive setup.
C. The fixture runs before every test function, ensuring fresh resources.
D. The fixture runs after each test to clean up resources immediately.

Solution

  1. Step 1: Understand fixture scopes in pytest

    Fixtures with scope='module' run once per module, not per test function.
  2. Step 2: Relate scope to expensive resource usage

    Running setup once per module saves time by avoiding repeated expensive setups for each test.
  3. Final Answer:

    The fixture setup runs once per module, reducing repeated expensive setup. -> Option B
  4. Quick Check:

    Module scope = setup once per module [OK]
Hint: Module scope runs setup once per module, saving time [OK]
Common Mistakes:
  • Confusing module scope with function scope
  • Thinking setup runs before every test
  • Assuming cleanup runs immediately after each test
2. Which of the following is the correct syntax to define a pytest fixture that sets up a database connection once per test session?
easy
A. @pytest.fixture(scope='session')\ndef db_conn():\n pass
B. @pytest.fixture(scope='class')\ndef db_conn():\n pass
C. @pytest.fixture(scope='module')\ndef db_conn():\n pass
D. @pytest.fixture(scope='function')\ndef db_conn():\n pass

Solution

  1. Step 1: Identify scope for once per test session

    The session scope runs the fixture setup once for the entire test session.
  2. Step 2: Match syntax with correct scope

    @pytest.fixture(scope='session')\ndef db_conn():\n pass uses @pytest.fixture(scope='session'), which is correct for this purpose.
  3. Final Answer:

    @pytest.fixture(scope='session')\ndef db_conn():\n pass -> Option A
  4. Quick Check:

    Session scope = setup once per session [OK]
Hint: Session scope means setup runs once per entire test run [OK]
Common Mistakes:
  • Using function scope for expensive shared resources
  • Confusing module and session scopes
  • Forgetting to specify scope in fixture decorator
3. Given the following pytest fixture and test code, what will be the output when running the tests?
@pytest.fixture(scope='module')
def resource():
    print('Setup resource')
    yield
    print('Cleanup resource')

def test_one(resource):
    print('Test one running')

def test_two(resource):
    print('Test two running')
medium
A. Setup resource\nTest one running\nTest two running\nCleanup resource
B. Setup resource\nTest one running\nCleanup resource\nSetup resource\nTest two running\nCleanup resource
C. Test one running\nTest two running
D. Setup resource\nCleanup resource\nTest one running\nTest two running

Solution

  1. Step 1: Understand module scope fixture behavior

    With scope='module', setup runs once before any tests in the module, and cleanup runs after all tests finish.
  2. Step 2: Trace the print statements during test execution

    First, 'Setup resource' prints. Then 'Test one running' and 'Test two running' print during tests. Finally, 'Cleanup resource' prints after all tests.
  3. Final Answer:

    Setup resource\nTest one running\nTest two running\nCleanup resource -> Option A
  4. Quick Check:

    Module scope = setup once before all tests, cleanup after all [OK]
Hint: Module scope runs setup once before all tests, cleanup after all [OK]
Common Mistakes:
  • Expecting cleanup after each test
  • Thinking setup runs before each test
  • Ignoring yield behavior in fixture
4. Identify the error in this pytest fixture code that aims to share a resource across tests in a class:
@pytest.fixture(scope='class')
def setup_resource():
    resource = open('file.txt')
    yield resource
    resource.close()

def test_example(setup_resource):
    assert setup_resource.readable()
medium
A. The fixture should use scope='module' instead of 'class'.
B. The fixture function name does not match the test parameter name.
C. The fixture does not handle exceptions during resource setup.
D. The fixture is missing the @pytest.mark.usefixtures decorator.

Solution

  1. Step 1: Review fixture resource setup and cleanup

    The fixture opens a file and yields it, then closes it after tests.
  2. Step 2: Check for error handling in setup

    If opening the file fails, no exception handling is present, which can cause test failures or resource leaks.
  3. Final Answer:

    The fixture does not handle exceptions during resource setup. -> Option C
  4. Quick Check:

    Missing exception handling in fixture setup = problem [OK]
Hint: Always handle exceptions in fixture setup to avoid leaks [OK]
Common Mistakes:
  • Confusing fixture scope requirements
  • Thinking @pytest.mark.usefixtures is mandatory
  • Assuming fixture name mismatch causes error
5. You want to share a database connection across multiple test classes but ensure it resets after all tests finish. Which pytest fixture pattern correctly achieves this?
hard
A. @pytest.fixture(scope='function')\ndef db_conn():\n conn = connect_db()\n yield conn\n conn.reset()\n conn.close()
B. @pytest.fixture(scope='class')\ndef db_conn():\n conn = connect_db()\n yield conn\n conn.close()
C. @pytest.fixture(scope='module')\ndef db_conn():\n conn = connect_db()\n yield conn\n conn.reset()
D. @pytest.fixture(scope='session')\ndef db_conn():\n conn = connect_db()\n yield conn\n conn.reset()\n conn.close()

Solution

  1. Step 1: Determine scope for sharing across multiple test classes

    Sharing across classes requires at least session scope to cover all tests.
  2. Step 2: Ensure resource resets after all tests finish

    Using yield allows cleanup code after tests; calling conn.reset() before conn.close() resets the connection properly.
  3. Final Answer:

    @pytest.fixture(scope='session')\ndef db_conn():\n conn = connect_db()\n yield conn\n conn.reset()\n conn.close() -> Option D
  4. Quick Check:

    Session scope + yield cleanup with reset = correct pattern [OK]
Hint: Use session scope and yield cleanup to reset shared resource [OK]
Common Mistakes:
  • Using too narrow scope like function or class
  • Forgetting to reset resource before closing
  • Not using yield to separate setup and cleanup