test-first — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited test-first (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Write the test that describes the behavior you want, watch it fail, then write the code that makes it pass. A test written before the code tests the requirement; a test written after tends to test whatever the code happens to do — bugs included.
Test-first is the Red → Green → Refactor loop: one behavior at a time, minimum code to pass, then clean up with the test as a safety net. Coverage is a side effect; confidence in behavior is the goal.
Pair with [[spec-first]] for requirements to test against, [[incremental-delivery]] to test each slice, [[source-first]] to verify interfaces before asserting them, [[fault-recovery]] for bug reproduction, [[browser-checks]] when the behavior is visual or interaction-heavy, and [[pipeline-ops]] to keep the suite fast and required in CI. For structure and doubles, see testing patterns; use the test-engineer agent for suite design and gap analysis.
Light TDD is fine for exploratory spikes — but promote or rewrite tests before merge; spikes without tests don't ship ([[review-gate]]).
Skip driving with tests for:
Not a substitute for [[browser-checks]] on UI-heavy flows — unit tests plus browser verification for layout, focus, and network timing.
| Situation | Test-first emphasis |
|---|---|
| New feature from spec | One test per requirement/scenario ([[spec-first]]) |
| Bug fix | Failing repro test → fix → green ([[fault-recovery]]) |
| Refactor | Characterization tests first if missing |
| Public API | Contract tests in CI ([[pipeline-ops]]) |
| LLM feature | Eval set as "tests" ([[llm-feature-engineering]]) |
Work in order. One behavior per cycle.
Pull behaviors from [[spec-first]] scenarios, ticket acceptance criteria, or a one-line bug report. If "expected behavior" is disputed, clarify before writing tests ([[spec-first]], [[fault-recovery]]).
Write the behavior as a single observable claim:
Good: "POST /orders with expired token returns 401 and no order row is created"
Bad: "test the orders module"Push detail to the fastest level that can catch the bug:
| Level | Use for | Avoid |
|---|---|---|
| Unit | Pure logic, validators, parsers, domain rules | Mocking every collaborator |
| Integration | DB, HTTP handler + service, module collaboration | Full browser |
| Contract | API request/response shape, event schema | Implementation internals |
| E2E | Critical user journeys, few in number | Every edge case (too slow/flaky) |
Tax calculation logic → unit
Create order persists row → integration
Checkout happy path → one e2e; edge cases lower downSee testing patterns for doubles and structure.
Test what callers observe — return value, HTTP status, DB state, emitted event, rendered text — not private methods or field values.
redirects_unauthenticated_user_to_login, not testAuth2Bad: expect(service.internalCache.size).toBe(1)
Good: expect(getUser(id)).toEqual({ id, name: 'Ada' })
Good: expect(response.status).toBe(401)Verify signatures and types against source ([[source-first]]) before asserting fantasy APIs.
A test that passes before implementation proves nothing — it isn't testing what you think.
Confirm the failure message matches missing behavior:
Good fail: Expected 401 but got 200
Bad fail: ReferenceError: createOrder is not defined (wrong — fix test setup first)
Bad pass: Test green before production code existsFor bug fixes, the repro test must fail on main with the bug present, then pass after the fix.
Implement just enough to green the test — no speculative features, no "while I'm here" refactors. YAGNI applies to production code too ([[incremental-delivery]]).
Run the narrowest test scope during the loop (single file, single case), then full suite before commit.
Once green, improve structure ([[simplify]]) — extract helpers, rename, remove duplication — re-run tests after each step. Refactoring without tests is gambling.
Don't change behavior in a refactor commit; behavior changes get new or updated tests first.
After happy path, add tests from the spec and testing patterns coverage list:
Prioritize by risk — payment beats tooltip color.
Mandatory sequence ([[fault-recovery]]):
No fix merges without a repro unless truly impossible — document why in the PR ([[review-gate]]).
No spec, messy code, need to refactor ([[simplify]]):
Characterization tests are scaffolding — replace with spec-driven tests when behavior is corrected.
For HTTP APIs, events, and shared modules ([[interface-design]]):
Contract tests protect callers; unit tests protect logic.
Tests that lie are worse than no tests.
sleep(1000) in unit testsLoose assertions that can't fail (toBeDefined() only) are red flags ([[review-gate]]).
| Mode | When | Rule |
|---|---|---|
| Strict TDD | New logic, clear spec | Red → green → refactor every behavior |
| Test-alongside | UI with heavy setup | Write test immediately after first manual proof; don't defer to PR end |
| Eval-first | LLM prompts/tools | Golden set + metrics before prompt tuning ([[llm-feature-engineering]]) |
| Browser proof | Layout, a11y, network | [[browser-checks]] after unit/integration; not a excuse for zero logic tests |
Even in test-alongside mode, no merge without automated tests for logic you own.
expect(true).toBe(true) or equivalent meaningless assertionsTest-first describes widely-used TDD practice. Written for this repo; patterns reference supplements detail.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.