# Example tests

An example test pairs a hand-picked input with an assertion about what
the code does with it. The assertion is usually an exact expected
value, but equally a property the output must satisfy, a round-trip
relation, or merely that nothing crashed. It is the foundational verification
technique in most codebases: the everyday categories of automated test are all
example tests, separated only by *how much of the system* they
exercise.

Example tests are the right tool when the relevant cases
are *small in number, enumerable, and known to the author*.
Past that range the author cannot write the cases out, and
[property-based testing](https://quality.stereobooster.com/property-based-testing.md) or
[fuzzing](https://quality.stereobooster.com/fuzzing.md) generates them instead.

## What it catches

- **Regressions of fixed bugs.** Once an example test captures the
  input that caused the bug, the same case cannot reach production
  silently again. Most regression suites are exactly this — a record
  of the failures already found.
- **Golden-path correctness.** The common, expected use of the
  feature works as specified.
- **Specified edge cases.** The empty list, the zero amount and the
  max capacity behave as the author wrote them down.
- **Behavior the spec enumerates.** A finite set of declared
  cases (state transitions, status codes, mode toggles) maps
  naturally to a finite set of example tests, one per case.
- **Documented examples.** Test as documentation: the test
  *is* the worked example a future reader needs.

## What example tests structurally cannot catch

**Example tests guarantee the absence of
known bugs, not the absence of bugs.** A regression test needs no
more than that: the bug it pins is already known.

## Tools

Every mainstream language has stable example-test infrastructure. The
runners named for each language are common defaults, not a complete
set.

- **JavaScript / TypeScript** — **[Vitest](https://vitest.dev/)** (modern default),
  **[Jest](https://jestjs.io/)**, **[node:test](https://nodejs.org/api/test.html)** (stdlib since Node 18), **[Mocha](https://mochajs.org/)**.
- **Python** — **[pytest](https://docs.pytest.org/)** (the de facto default), **unittest**
  (stdlib).
- **Rust** — `cargo test` (stdlib `#[test]`), **[nextest](https://nexte.st/)** for
  speed and richer reporting.
- **Go** — `go test` (stdlib).
- **Java / Kotlin** — **[JUnit 5](https://junit.org/junit5/)**, **[TestNG](https://testng.org/)**, **[Spock](https://spockframework.org/)**
  (Groovy).
- **Ruby** — **[RSpec](https://rspec.info/)**, **[Minitest](https://github.com/minitest/minitest)**.
- **C / C++** — **[GoogleTest](https://github.com/google/googletest)**, **[Catch2](https://github.com/catchorg/Catch2)**, **[doctest](https://github.com/doctest/doctest)**.
- **C#** — **[xUnit.net](https://xunit.net/)**, **[NUnit](https://nunit.org/)**, **[MSTest](https://github.com/microsoft/testfx)**.
- **PHP** — **[PHPUnit](https://phpunit.de/)**, **[Pest](https://pestphp.com/)**.
- **Elixir** — **[ExUnit](https://hexdocs.pm/ex_unit/ExUnit.html)** (stdlib).

Most of these support: fixtures, parameterized tests (one
example body × multiple input rows), parallel execution, and
[snapshot/approval](https://quality.stereobooster.com/snapshot-testing.md) captures.

## When to use, when not

**Use example tests:**

- **For every bug fix** — pin the case as a regression.
- For **specified, finite behavior** — a state machine with a
  handful of transitions; a function with three error codes.
- As **golden-path system tests** — one happy-path scenario per
  high-value flow, exercised through the assembled system.
- For **smoke checks** at a deploy boundary — fast, heuristic-tier,
  deliberately limited.
- As **documentation**. A failing test is a precise bug report;
  a passing test is an executable example.
- When **other methods would be overkill**. A configuration
  loader with three valid shapes and two error cases doesn't
  need a property-based test; three example tests are correct.

**Don't lean only on example tests when:**

- The input space is **rich and irregular** — parsers,
  encoders, numerical code, ML, anything that takes "data with
  structure". Combine with
  [property-based testing](https://quality.stereobooster.com/property-based-testing.md),
  [fuzzing](https://quality.stereobooster.com/fuzzing.md),
  [metamorphic testing](https://quality.stereobooster.com/metamorphic-testing.md), or
  [differential testing](https://quality.stereobooster.com/differential-testing.md). Example
  tests still belong in the suite for the cases that specifically
  matter; they are not the primary input.
- The code is **concurrent or distributed**. State-space
  explosion makes hand-enumeration insufficient; see
  [deterministic simulation
  testing](https://quality.stereobooster.com/deterministic-simulation-testing.md) and
  [model checking](https://quality.stereobooster.com/model-checking.md).
- The boundary is **security-sensitive**. Pair with
  [fuzzing](https://quality.stereobooster.com/fuzzing.md),
  [threat modeling](https://quality.stereobooster.com/threat-modeling.md), and
  [static analysis](https://quality.stereobooster.com/static-analysis.md).
- AI generated the code. AI's bugs are *plausibly-shaped,
  locally-coherent, subtly wrong* — exactly the kind that hides
  between AI-generated code and AI-generated example tests written
  from the same intuition. The other methods don't share that
  intuition.

## Evidence

There is no controlled study of example tests as a technique: example-based
testing is the baseline other methods are measured against. The case for it is
definitional rather than empirical. A suite of N example tests establishes only
that the code behaves correctly on those N inputs.

## Classification

- **Quality dimensions:** Functionality, Maintainability (as a regression / snapshot refactor-safety net).
- **Area:** Regression prevention, golden-path coverage, bug-fix verification, fast-feedback during development; any code with small, enumerable behavior the author can pin down by hand.
- **Guarantee:** Empirical — *the cases tried passed*.

## Referenced by

- [Functionality](https://quality.stereobooster.com/functionality.md) · Quality dimensions
- [Quality dimensions](https://quality.stereobooster.com/quality-dimensions.md) · Quality dimensions
- [Effect scope](https://quality.stereobooster.com/effect.md) · The axes
- [Guarantee](https://quality.stereobooster.com/guarantee.md) · The axes
- [Oracle](https://quality.stereobooster.com/oracle.md) · The axes
- [Code review](https://quality.stereobooster.com/code-review.md) · Methods
- [Combinatorial and pairwise testing](https://quality.stereobooster.com/combinatorial-testing.md) · Methods
- [Microbenchmarking](https://quality.stereobooster.com/microbenchmarking.md) · Methods
- [Profiling](https://quality.stereobooster.com/profiling.md) · Methods
- [Property-based testing](https://quality.stereobooster.com/property-based-testing.md) · Methods
- [Snapshot and approval testing](https://quality.stereobooster.com/snapshot-testing.md) · Methods
- [Statistical and sampling testing](https://quality.stereobooster.com/statistical-testing.md) · Methods
- [Temporal-logic falsification](https://quality.stereobooster.com/temporal-logic-falsification.md) · Methods
- [Testing GUI and mobile applications](https://quality.stereobooster.com/testing-gui-and-mobile-apps.md) · Methods
- [Playwright](https://quality.stereobooster.com/playwright.md) · Recipes
- [How AI fits into software quality](https://quality.stereobooster.com/ai.md) · AI
- [Glossary](https://quality.stereobooster.com/glossary.md) · Overview
