Framework Architecture & CI/CD · Lesson 3 of 6

Test Data: Fixtures vs Factories vs Seeding

Every test needs data to work on. There are four ways to get it, and picking the right one — and defending your choice — is a real skill.

By Shahriyar · Updated

The idea, in one line

Get your test's data from the lowest layer that's still reliable, and check your result at the layer you're actually testing. Everything below is how to do that well.

The four strategies

▸ try it
import pytest

# Factory: fresh, independent data per test
def make_user(**overrides):
    base = {"email": "t@example.com", "plan": "free", "verified": True}
    return {**base, **overrides}

# Fixture: API-seed a real user, then clean up after
@pytest.fixture
def seeded_user(api_client):
    payload = make_user(plan="pro")
    resp = api_client.post("/users", json=payload)   # seed via the app's API
    user = resp.json()
    yield user                                       # test runs here
    api_client.delete(f"/users/{user['id']}")        # teardown

def test_pro_dashboard(seeded_user, ui):
    ui.login(seeded_user)
    assert ui.dashboard.badge() == "PRO"

Read it top to bottom: the factory makes clean data, the fixture uses that data to seed a real user through the API, the test runs at the yield, and everything after yield cleans up. Whatever you create, you remove.

Advanced — the heuristic to say out loud

Seed setup at the lowest reliable layer, then assert at the layer under test. Prefer API seeding over DB seeding unless speed forces your hand — DB seeding is fast but bypasses the app's own rules, so it can create states that could never happen for a real user.

Grounded in the pytest fixtures docs and the factory_boy documentation

All lessons in Framework Architecture & CI/CD

  1. Designing a Framework from Scratch: The Layers
  2. The Four Patterns SDETs Actually Use
  3. Test Data: Fixtures vs Factories vs Seeding
  4. CI with GitHub Actions: Run UI + API on Every Push
  5. Docker & Selenium Grid: Reproducible Test Environments
  6. Parallel, Retries & Flaky-Test Quarantine