Sanity Testing
What it is
Section titled “What it is”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 netA 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”.
When to use it / when to avoid it
Section titled “When to use it / when to avoid 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
Frameworks & tools
Section titled “Frameworks & tools”| 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 |
Quick setup
Section titled “Quick setup”npx vitest run src/checkout/checkout.test.ts# or a tagged slicenpx playwright test --grep @sanitypytest tests/test_checkout.py -k "discount" -qgo test ./pkg/checkout/... -run TestDiscount -count=1<!-- Maven: run a single folder of sanity tests --><configuration> <includes> <include>**/sanity/*Test.java</include> </includes></configuration>dotnet test --filter "FullyQualifiedName~CheckoutTests"Example
Section titled “Example”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'); });});from apply_coupon import apply_coupon
def test_rejects_expired_coupon(): result = apply_coupon("EXPIRED10", expires="2020-01-01") assert result["error"] == "coupon_expired"func TestSanityRejectsExpiredCoupon(t *testing.T) { res := ApplyCoupon("EXPIRED10", "2020-01-01") if res.Error != "coupon_expired" { t.Fatalf("want coupon_expired, got %q", res.Error) }}import static org.junit.jupiter.api.Assertions.assertEquals;import org.junit.jupiter.api.Test;
class CouponSanityTest { @Test void rejectsExpiredCoupon() { var result = Coupon.apply("EXPIRED10", "2020-01-01"); assertEquals("coupon_expired", result.error()); }}using Xunit;
public class CouponSanityTests{ [Fact] public void RejectsExpiredCoupon() { var result = Coupon.Apply("EXPIRED10", "2020-01-01"); Assert.Equal("coupon_expired", result.Error); }}Anti-patterns & best practices
Section titled “Anti-patterns & best practices”- 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
Section titled “Self-assessment quiz”Self-assessment quiz
Pick one answer per question, then press Check answers.