Python · The language, not just syntax

How do you write maintainable tests with pytest?

MediumpytestfixturestestingUpdated Oct 2026
Quiz this track

Short answer

Structure tests around behaviour, use fixtures for setup and teardown, parametrize inputs, and keep shared configuration in conftest.py. Assertions are plain assert statements with rich failure output.

pytest discovers functions named test_ and runs them with fixtures injected by name. Fixtures can be scoped to a function, module or session, which keeps expensive setup shared without leaking state between tests. Plain assert statements are rewritten to show the compared values on failure.

python
import pytest

@pytest.fixture
def account():
    return Account(owner="Asha", balance=100)

@pytest.mark.parametrize(
    "amount,expected",
    [(50, 50), (100, 0), (150, -50)],
)
def test_withdraw(account, amount, expected):
    account.withdraw(amount)
    assert account.balance == expected

def test_rejects_negative(account):
    with pytest.raises(ValueError):
        account.withdraw(-1)
The fixture provides a fresh account per test. Parametrize turns one test into three cases with clear ids.

Practices that scale

  • Test observable behaviour, not private implementation details
  • Use tmp_path for filesystem tests and monkeypatch for environment or attributes
  • Mark slow or integration tests so the fast suite stays quick in CI
  • Use coverage to find untested branches, not as a target to game

Fixtures should be explicit about their scope. A session-scoped fixture that mutates shared state will create order-dependent failures. Keep tests independent so they can run in any order and in parallel.

A test that passes regardless of the code is worse than no test. When fixing a bug, write a failing test first, then fix the code and watch it pass.

Follow-ups you should expect

Interviewers use these to check whether the first answer was understanding or memorisation.

  1. 1What is the purpose of conftest.py?
  2. 2When would you use a session-scoped fixture?
  3. 3How do you test that an exception is raised?
  4. 4Why are order-dependent tests a problem?

Say it in the interview

I write pytest tests around observable behaviour, use fixtures for setup and teardown, and parametrize cases instead of duplicating test bodies. Shared configuration goes in conftest.py, and I keep fixtures at the narrowest scope that still saves time. I mark slow integration tests separately and use coverage to find gaps, not to hit an arbitrary number. Tests must be independent so they can run in any order.

Use this as a model, not a script. Saying it in your own words is what makes it survive follow-up pressure.

Related questions

Reading is step one

Now say it out loud.

Understanding an answer and delivering it under pressure are different skills. Rehearse this topic in a live Python mock interview and get scored feedback on depth, clarity and confidence.