A characterization test is a snapshot of actual behavior

Lightweight characterization is a small test that records what code does now in a specific scenario before refactoring. It protects a narrow area from accidental change, but does not claim that the current behavior is business-correct.

This test complements unit, integration, and regression tests; it does not replace them.

When it fitsWhy
One method or local flowThe area is easy to bound
A full integration test is too broadA cheap safety net is needed
There are one or two key scenariosIt is enough to capture the main results
Existing coverage is limitedA baseline is needed before a structural change

Test observable behavior

  • response status;
  • error code or reason;
  • message;
  • external side effect;
  • another part of the public result.

Example for finalizeOrder

The test calls public finalizeOrder and checks the result. If a helper is renamed, combined, or removed during refactoring, the assertions should remain valid.

ScenarioExpected current result
Payment succeeds, item is in stockStatus FINALIZED and the corresponding message
Payment succeeds, stock is zeroStatus REJECTED and reason OUT_OF_STOCK
Bounded characterization prompt
Target: finalizeOrder
Scenarios: one successful and one boundary case
Add only 1-2 behavior tests.
Do not change production code.
Capture current behavior; do not call it business-correct.

A lightweight characterization cycle

  1. Describe in words the behavior to protect.
  2. Add one or two narrow tests.
  3. Run them against the current implementation.
  4. Make one small structural change.
  5. Run characterization and the main harness.
  6. Check the diff and only then create a commit.

When characterization is insufficient

  • a large module with many integrations;
  • queues, a database, and numerous side effects;
  • a change spanning several packages;
  • an updated external contract;
  • business rules changing at the same time.

Canonical lesson source · JavaRush

Open JavaRush material