Skip to content

Sanity Testing

A sanity test is a narrow, focused check that a specific change or bug fix works as intended. It is the opposite shape to smoke: deep but not wide. You do not sweep the whole system — you confirm one area behaves after a change, before investing in a fuller test pass.

change ──► SANITY (one area, deep) ──► regression / full suite
│ pass │
└ fail → fix, do not proceed └ wider safety net

A useful contrast: smoke is a shallow sweep of the whole build; sanity is a deep look at one slice. Smoke says “the build is alive”; sanity says “this fix actually fixed it”.

Use it for

  • Right after a bug fix or a small change, before running the full suite
  • Confirming a specific feature you just touched still behaves
  • A quick accept/reject gate on a candidate build for one area

Avoid it when

  • You need to know the whole build is stable → use smoke testing
  • You need to prove the change did not break anything else → follow with a regression test
  • The change is broad or architectural — sanity’s narrow scope will miss knock-on effects
Tool Ecosystem Notes
Vitest / Jest JS/TS Run a single file: vitest run path/to/feature
Playwright Multi --grep a feature by tag or title
pytest Python pytest tests/test_feature.py -k "checkout"
Go testing Go go test ./pkg/checkout/...
JUnit 5 Java/JVM Run one class or @Tag via Surefire
xUnit / NUnit .NET dotnet test --filter FullyQualifiedName~Checkout
Robot Framework Python Select a tag: robot --include sanity tests/
Postman / Newman Multi Replay the affected requests only
Terminal window
npx vitest run src/checkout/checkout.test.ts
# or a tagged slice
npx playwright test --grep @sanity
import { describe, it, expect } from 'vitest';
import { applyCoupon } from './apply-coupon';
describe('applyCoupon (sanity after the fix)', () => {
it('rejects an expired coupon', () => {
const result = applyCoupon('EXPIRED10', { expires: '2020-01-01' });
expect(result.error).toBe('coupon_expired');
});
});
  • Keep it narrow. One change, one area; if it is sweeping the whole system, it is smoke.
  • Pick the assert that proves the fix. Target the exact behaviour the bug broke.
  • Do not stop at sanity. Sanity confirms the fix; a regression pass confirms nothing else broke.
  • Reuse existing tests. Prefer selecting a slice of the suite over writing throwaway code.
  • Time-box it. Sanity should be minutes; long sessions mean you are doing regression.
  • Make the target explicit. Tag or filter so “run sanity” is one deterministic command.

Self-assessment quiz

Pick one answer per question, then press Check answers.

  1. How does a sanity test differ from a smoke test?
  2. When is a sanity test most useful?
  3. You just fixed a bug. You run one focused test and it passes. What should you do next?
  4. Which command selects a sanity slice in pytest?
  5. Which is a smell that you have drifted out of sanity testing?