What if you could save minutes on every test run by sharing one setup smartly?
Why Shared expensive resource patterns in PyTest? - Purpose & Use Cases
Start learning this pattern below
Jump into concepts and practice - no test required
Imagine you have a big database or a complex server setup that your tests need to use. You run each test one by one, and every time, you start and stop this heavy setup manually.
This manual way is slow because starting and stopping the resource takes a lot of time. It's also easy to make mistakes, like forgetting to clean up or accidentally changing the resource state, which breaks other tests.
Shared expensive resource patterns let you set up the resource once and share it across many tests safely. This saves time and avoids errors by managing the resource automatically and cleanly.
def test1(): setup_db() # test code teardown_db() def test2(): setup_db() # test code teardown_db()
@pytest.fixture(scope='session') def db(): setup_db() yield teardown_db() def test1(db): # test code def test2(db): # test code
It enables running many tests faster and more reliably by sharing costly setups without repeating work.
Think of running tests that need a web server. Instead of starting the server for each test, you start it once for all tests, saving minutes and avoiding server crashes.
Manual setup of expensive resources slows tests and causes errors.
Shared resource patterns set up once and reuse safely.
Tests run faster and more reliably with less manual work.
Practice
scope='module' when dealing with expensive resources?Solution
Step 1: Understand fixture scopes in pytest
Fixtures withscope='module'run once per module, not per test function.Step 2: Relate scope to expensive resource usage
Running setup once per module saves time by avoiding repeated expensive setups for each test.Final Answer:
The fixture setup runs once per module, reducing repeated expensive setup. -> Option BQuick Check:
Module scope = setup once per module [OK]
- Confusing module scope with function scope
- Thinking setup runs before every test
- Assuming cleanup runs immediately after each test
Solution
Step 1: Identify scope for once per test session
Thesessionscope runs the fixture setup once for the entire test session.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.Final Answer:
@pytest.fixture(scope='session')\ndef db_conn():\n pass -> Option AQuick Check:
Session scope = setup once per session [OK]
- Using function scope for expensive shared resources
- Confusing module and session scopes
- Forgetting to specify scope in fixture decorator
@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')Solution
Step 1: Understand module scope fixture behavior
Withscope='module', setup runs once before any tests in the module, and cleanup runs after all tests finish.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.Final Answer:
Setup resource\nTest one running\nTest two running\nCleanup resource -> Option AQuick Check:
Module scope = setup once before all tests, cleanup after all [OK]
- Expecting cleanup after each test
- Thinking setup runs before each test
- Ignoring yield behavior in fixture
@pytest.fixture(scope='class')
def setup_resource():
resource = open('file.txt')
yield resource
resource.close()
def test_example(setup_resource):
assert setup_resource.readable()Solution
Step 1: Review fixture resource setup and cleanup
The fixture opens a file and yields it, then closes it after tests.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.Final Answer:
The fixture does not handle exceptions during resource setup. -> Option CQuick Check:
Missing exception handling in fixture setup = problem [OK]
- Confusing fixture scope requirements
- Thinking @pytest.mark.usefixtures is mandatory
- Assuming fixture name mismatch causes error
Solution
Step 1: Determine scope for sharing across multiple test classes
Sharing across classes requires at leastsessionscope to cover all tests.Step 2: Ensure resource resets after all tests finish
Usingyieldallows cleanup code after tests; callingconn.reset()beforeconn.close()resets the connection properly.Final Answer:
@pytest.fixture(scope='session')\ndef db_conn():\n conn = connect_db()\n yield conn\n conn.reset()\n conn.close() -> Option DQuick Check:
Session scope + yield cleanup with reset = correct pattern [OK]
- Using too narrow scope like function or class
- Forgetting to reset resource before closing
- Not using yield to separate setup and cleanup
