backend / testing / pytest / 02_pytest_concepts.md

What pytest concepts do you use (fixture, parametrize, scope)?

4 interview angles 2 min read source

What pytest concepts do you use (fixture, parametrize, scope)?

Answer

Fixtures

  • Fixtures provide test dependencies: DB connections, API clients, sample data, mocks. Define with @pytest.fixture; pytest injects them into test functions by name. Use them to avoid repeating setup/teardown and to share resources across tests.
  • Example: def db(): ... yield session; session.close() — the test receives db; teardown runs after the test. Use request.getfixturevalue("fixture_name") when you need a fixture dynamically.

Parametrize

  • @pytest.mark.parametrize("arg1,arg2", [(a1, a2), (b1, b2)]) runs the same test with different inputs. Each tuple is one case; pytest reports pass/fail per case. Use it for boundary values, multiple inputs, or “same logic, different data” without writing duplicate tests.
  • Combine with fixtures: parametrize can reference fixture names; pytest builds the cartesian product of parametrized args and fixtures when needed. Use pytest.param(..., id="custom_id") to get readable test IDs.

Scope

  • Fixture scope controls how often the fixture is created: function (default, per test), class (per test class), module (per file), package (per package), session (per test run). Larger scope = fewer creations, but shared state; use for expensive setup (e.g. DB, server) when tests don’t mutate it. Use scope="session" with care to avoid cross-test pollution.
  • Example: @pytest.fixture(scope="module") for a single DB connection shared by all tests in the module; use autouse=True if every test in the scope should get it without naming it.

Other useful bits

  • conftest.py: put shared fixtures here; they’re visible to tests in that directory and below.
  • pytest.raises(SomeError), pytest.warns(): assert exceptions and warnings.
  • pytest.approx(): compare floats without brittle equality.

Interview angle

  • “What makes a fixture better than setUp?” - explicit dependency by parameter name, composability (fixtures requesting fixtures), and scoping, so an expensive resource is created once per session while cheap state is per test.
  • “Which scope do you choose?” - the widest that’s still safe. A database container at session scope with a per-test transaction rollback gives fast, isolated tests; recreating the container per test makes the suite unusable.
  • “How do you test many input combinations?” - @pytest.mark.parametrize, which produces one reported test per case, so a failure names the exact input. A loop inside one test hides which case failed and stops at the first.
  • “What’s conftest.py for?” - fixtures shared across a directory without importing. Placement matters: it applies to its directory and below, which is how you scope test infrastructure by area.