Fixtures and fixture scope

RoadmapsPython

Overview

A **fixture** is a function that sets up data or state before a test runs. We use the `@pytest.fixture` decorator to mark it. **Scope** controls how often the fixture runs: once per test (the default), or once per entire session. Here is a worked example creating a student dictionary: ```python import pytest @pytest.fixture def student_data(): print('Creating student') return {'name': 'Arjun', 'marks': 85} def test_name(student_data): assert student_data['name'] == 'Arjun' def test_marks(student_data): assert student_data['marks'] == 85 ``` pytest runs `student_data` before `test_name`, and then runs it again before `test_marks`. It provides fresh data every time because its scope is function-level by default. Now, look at this faded example where one step is blank: ```python import pytest @pytest._______ def empty_cart(): return [] def test_cart_empty(empty_cart): assert len(empty_cart) == 0 ``` To turn `empty_cart` into a fixture, we fill in the blank with `fixture`.

Without fixtures, you repeat setup code in every single test. Fixtures keep test files clean and ensure each test gets a fresh, predictable starting state.

Where used: pytest test suites, Database connections in tests

Why learn this

Code walkthrough

import pytest

@pytest.fixture
def config():
  return {'mode': 'test'}

def test_config(config):
  print(config['mode'])
  assert config['mode'] == 'test'

test_config({'mode': 'test'})

Focus: def test_config(config):

Aha moment

import pytest

@pytest.fixture
def user():
  return {'name': 'Rahul'}

def test_change(user):
  user['name'] = 'Amit'

def test_check(user):
  print(user['name'])

# Simulating what pytest does:
t1_user = user()
test_change(t1_user)
t2_user = user()
test_check(t2_user)

Prediction: What does test_check print?

Common guess: Amit

It prints 'Rahul'. The default scope is 'function', so pytest creates a completely fresh dictionary for `test_check`. The mutation in `test_change` is forgotten.

Common mistakes

Recall questions

Understanding checks

What does test_two print?

2

The default scope is 'function', so the fixture runs a second time before `test_two`, incrementing the global counter to 2.

How many times does 'Connecting to DB' print when these tests run?

Exactly once.

Because the scope is 'session', pytest runs the fixture only once for the entire test run, and shares the result with both tests.

Practice tasks

Set the scope

Given this code, change the fixture so it only runs once per test session.

Challenge

Create and use a fixture

Create a fixture named `my_list` that returns `[1, 2]`. Then write a test function named `test_list` that requests the fixture and asserts its length is 2.

Continue learning

Previous: Test discovery and naming conventions

Next: conftest.py: shared fixtures

Return to Python Roadmap