Fixture scope with parallel tests in PyTest - Build an Automation Script
Start learning this pattern below
Jump into concepts and practice - no test required
import pytest setup_counter = 0 teardown_counter = 0 @pytest.fixture(scope='module') def resource(): global setup_counter setup_counter += 1 print(f'Setup called {setup_counter} time(s)') yield global teardown_counter teardown_counter += 1 print(f'Teardown called {teardown_counter} time(s)') def test_one(resource): assert True def test_two(resource): assert True if __name__ == '__main__': import subprocess # Run pytest with 2 parallel workers result = subprocess.run(['pytest', '-n', '2', '--capture=no'], capture_output=True, text=True) print(result.stdout) # Check output for setup/teardown counts setup_runs = result.stdout.count('Setup called') teardown_runs = result.stdout.count('Teardown called') assert setup_runs == 2, f'Expected 2 setup calls, got {setup_runs}' assert teardown_runs == 2, f'Expected 2 teardown calls, got {teardown_runs}' assert 'failed' not in result.stdout.lower(), 'Some tests failed'
This code defines a pytest fixture resource with module scope. It increments counters and prints messages when setup and teardown run.
Two test functions use this fixture. When running with pytest-xdist using 2 workers (-n 2), the fixture setup and teardown run once per worker, so twice total.
The __main__ block runs pytest programmatically with parallel workers and captures output. It counts how many times the setup and teardown messages appear to verify the fixture scope behavior.
Assertions check that both tests pass and the fixture setup/teardown run exactly twice, matching the expected behavior for module scope with parallel workers.
This approach helps beginners see how fixture scope affects parallel test runs and how to verify it.
Now add data-driven testing with 3 different inputs using the same fixture and verify fixture setup runs only twice total
Practice
scope='session' parameter in a pytest fixture control?Solution
Step 1: Understand fixture scopes in pytest
Pytest fixtures can have different scopes like function, class, module, and session, which control how often the fixture setup runs.Step 2: Identify what session scope means
Session scope means the fixture runs only once for the entire test session, regardless of how many tests use it.Final Answer:
The fixture runs once per entire test session. -> Option AQuick Check:
scope='session' = runs once per session [OK]
- Confusing session scope with function scope
- Thinking session scope runs per test module
- Assuming session scope runs per test class
Solution
Step 1: Recall pytest fixture syntax
Pytest fixtures use the decorator@pytest.fixture()with optional parameters likescopeas a string.Step 2: Identify correct scope parameter usage
The scope parameter must be a string, soscope='session'is correct. Options C and D are invalid syntax.Final Answer:
@pytest.fixture(scope='session') -> Option BQuick Check:
Correct syntax uses scope='session' string [OK]
- Omitting quotes around 'session'
- Using invalid keyword arguments
- Confusing scope with boolean flags
@pytest.fixture(scope='session')
def resource():
print('Setup resource')
yield
print('Teardown resource')
def test_a(resource):
pass
def test_b(resource):
passHow many times will 'Setup resource' be printed during the entire test run?
Solution
Step 1: Understand session scope with parallel workers
When running tests in parallel with pytest-xdist, each worker runs its own session, so session-scoped fixtures run once per worker.Step 2: Calculate total setup calls
With 2 workers, the fixture setup runs once per worker, so 'Setup resource' prints twice.Final Answer:
Twice -> Option CQuick Check:
Session scope runs once per worker = 2 times [OK]
- Assuming session scope runs only once globally
- Ignoring parallel worker count
- Confusing function scope with session scope
Solution
Step 1: Identify why session scope runs multiple times
In parallel testing, session scope runs once per worker, so with 3 workers, setup runs 3 times.Step 2: Understand how to share fixture state globally
To run setup only once globally, you must share state outside pytest workers, e.g., via a database or external service.Final Answer:
Cause: session scope runs per worker; Fix: use a database or external service to share state. -> Option DQuick Check:
Session scope per worker needs external sharing [OK]
- Thinking session scope runs once globally in parallel
- Changing scope to function instead of sharing state
- Ignoring parallel execution effects
Solution
Step 1: Understand session scope behavior with parallel workers
Session scope runs once per worker, so with 4 workers, setup runs 4 times unless shared externally.Step 2: Identify how to run setup only once globally
Implementing external resource locking (like a file lock or database flag) ensures only one worker runs the expensive setup.Final Answer:
Use scope='session' fixture and implement external resource locking (e.g., file lock or database). -> Option AQuick Check:
External locking + session scope = single global setup [OK]
- Assuming pytest-xdist shares session fixtures automatically
- Using function scope and expecting single setup
- Running tests sequentially defeats parallel purpose
