Synthetic Industry

Platform · updated 2026-10-11

pytest: fixtures, patching and markers, and where test suites quietly go wrong

How pytest's fixture scopes, monkeypatch, temporary directories and skip or xfail markers shape test reliability, with the guide for each pattern and the bounded jobs that fit.

What pytest gives you for isolation

pytest's design gives a test suite most of the tools for keeping tests apart, and most reliability problems come from not using them. Fixtures have five scopes with function as the default, which means each test gets a fresh instance and the fixture is destroyed when the test ends. Wider scopes share one instance across several tests. The monkeypatch fixture undoes every change it made when the requesting test or fixture finishes. The tmp_path fixture gives each test function its own temporary directory. Used consistently, these keep a test from leaving anything behind for the next one.

  • Prefer function scope unless creating the fixture is expensive and the object is not changed.
  • Make changes to the environment through monkeypatch, so they are undone automatically.
  • Write files into the per-test temporary directory, never into a fixed path.

Where suites quietly go wrong

Three patterns recur. State shared through a wide fixture or a module-level object makes a test pass alone and fail in the suite. Dependence on the clock, random values or the machine makes a test fail at certain times or places. And markers added to make a build go green, skip or xfail, hide a test without recording who owns it or when it comes back. By default neither XFAIL nor XPASS fails the suite, so a marked test can be silently broken or silently fixed for months. Each pattern has a guide here that shows how to prove the cause before changing anything.

  • Test passes alone, fails in the suite: read the guide on shared state.
  • Test fails at some times or places: read the guide on the clock, randomness and environment.
  • A test has been skipped or marked for months: read the guide on what each marker hides.

What pytest does not do for you

pytest does not tell you whether your tests would catch a real change in behaviour, and a coverage figure does not either. It does not decide which tests to quarantine or when. It reports skipped, xfailed and xpassed tests only if you ask it to, with the report option that lists them. And it does not make a suite fast or the code under test deterministic: a function that reads the clock is still reading the clock. Those jobs belong to people who read the results.

  • Show the skip and xfail counts in the CI output so the numbers are read.
  • Judge a suite by whether deliberate changes make tests fail, not by a percentage.

Ask for the right work

Three bounded jobs fit a pytest suite. A regression suite around one named module records what it does now and is accepted by a seeded-change check; its published test price is £595. Stabilising up to five named flaky tests is quoted per test, from £395 for one test. A project to stabilise a whole suite is quoted from £2,400 from what your CI history shows, with a price cap, before we have any access to your code; it then starts by measuring the suite once you have agreed. All prices are untested hypotheses, nothing is charged until terms are agreed in writing, and we have not delivered these jobs for a client before. The work is not limited to pytest; the guides use it because its documentation is explicit about isolation. Send the module or test names, the runner and where tests run; do not send code or credentials.

Sources and limits