agentsclimarketplace

Tdd

Skill bllshttng/footnote/skills/tdd

Test-Driven Development: Write test first, watch it fail, implement minimal code. Use when: implementing any feature or bugfix, before writing production code, during /execute workflow, whenever acceptance criteria exist.From its SKILL.md

Install
npx -y skills add bllshttng/footnote --skill tdd

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

6.9 KB, as published. Nobody here has run it

Test-Driven Development (TDD)

Core principle: If you didn't watch the test fail, you don't know if it tests the right thing.

Write the test first. Watch it fail. Write minimal code to pass.

The Iron Law

NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST

Write code before the test? Delete it. Start over.

Red-Green-Refactor Cycle

    ┌──────┐
    │ RED  │ Write failing test
    └──┬───┘
       │ Verify: test FAILS correctly
       ▼
    ┌──────┐
    │GREEN │ Write minimal code to pass
    └──┬───┘
       │ Verify: test PASSES
       ▼
    ┌────────┐
    │REFACTOR│ Clean up (keep green)
    └──┬─────┘
       │
       ▼
    Next cycle

The Process

1. RED - Write Failing Test

Write ONE minimal test showing expected behavior.

Good test structure:

// tests/journeys/ratio-compliance.spec.ts
test('AC1-HP: calculates staff-to-child ratio correctly', async ({ page }) => {
  // Given: 2 staff signed in, 10 children signed in
  await loginAs(page, 'staff')
  await setupTestData({ staff: 2, children: 10, ageGroup: 'toddler' })

  // When: viewing ratio dashboard
  await page.goto('/app/ratio')

  // Then: shows 1:5 ratio (10 children / 2 staff)
  await expect(page.getByTestId('ratio-display')).toContainText('1:5')

  // And: database reflects correct calculation
  const snapshot = await assertRecordExists('ratio_snapshots', {
    facility_id: testFacilityId
  })
  expect(snapshot.ratio).toBe(5)
})

Requirements:

  • One behavior per test
  • Clear name (matches acceptance criterion)
  • Real assertions (UI + database)
  • No mocks unless absolutely necessary

2. Verify RED - Watch It Fail

MANDATORY. Never skip.

pnpm test tests/journeys/ratio-compliance.spec.ts

Confirm:

  • Test fails (not errors)
  • Failure message is expected
  • Fails because feature is missing (not typos)

Test passes immediately? You're testing existing behavior. Write different test.

Test errors? Fix error, re-run until it fails correctly.

3. GREEN - Write Minimal Code

Write the simplest code to make the test pass.

// Good: Just enough to pass
async function calculateRatio(facilityId: string) {
  const staff = await getSignedInStaff(facilityId)
  const children = await getSignedInChildren(facilityId)
  return children.length / staff.length
}

// Bad: Over-engineered
async function calculateRatio(facilityId: string, options?: {
  ageGroup?: string
  timeWindow?: number
  includeBreakStaff?: boolean
}) {
  // YAGNI - not requested by test
}

Don't:

  • Add features beyond what test requires
  • Refactor other code
  • "Improve" beyond the test

4. Verify GREEN - Watch It Pass

MANDATORY.

pnpm test tests/journeys/ratio-compliance.spec.ts

Confirm:

  • Test passes
  • Other tests still pass
  • No errors or warnings

Test still fails? Fix implementation, not test.

4b. Verify Database State (when applicable)

After tests pass (Green), verify the actual data store:

  • Query the database directly (not through the API being tested)
  • Confirm rows were created/updated/deleted as expected
  • Check constraints, indexes, and referential integrity
  • UI/API response success alone is INSUFFICIENT — the DB is the source of truth
// Example: verify database after API test passes
const record = await db.query('SELECT * FROM staff WHERE facility_id = $1', [facilityId])
expect(record.rows).toHaveLength(1)
expect(record.rows[0].status).toBe('active')

5. REFACTOR - Clean Up

Only after green. Keep tests passing.

  • Remove duplication
  • Improve names
  • Extract helpers

Don't add behavior.

6. Commit

git add .
git commit -m "feat(ratio): calculate staff-to-child ratio"

Acceptance Criteria as Tests

Each acceptance criterion from /blueprint becomes a test:

CriterionTest Name
AC1-HP: Happy pathtest('AC1-HP: happy path behavior')
AC2-ERR: Error statetest('AC2-ERR: handles invalid input')
AC3-UI: UI updatestest('AC3-UI: updates display on change')
AC4-EDGE: Edge casetest('AC4-EDGE: handles boundary condition')

Bug Fix Pattern

Bug: Empty email accepted

// 1. RED: Write test that fails
test('AC2-ERR: rejects empty email', async ({ page }) => {
  await page.fill('[name="email"]', '')
  await page.click('button[type="submit"]')
  await expect(page.getByRole('alert')).toContainText('Email required')
})

// 2. Verify RED: Run test, confirm it fails
// $ pnpm test -> FAIL: expected 'Email required'

// 3. GREEN: Fix the bug
function validateEmail(email: string) {
  if (!email?.trim()) {
    return { error: 'Email required' }
  }
  // ...
}

// 4. Verify GREEN: Run test, confirm it passes
// $ pnpm test -> PASS

// 5. REFACTOR: If needed

// 6. Commit

Common Rationalizations

ExcuseReality
"Too simple to test"Simple code breaks. Test takes 30 seconds.
"I'll test after"Tests passing immediately prove nothing.
"Already manually tested"Ad-hoc != systematic. No record, can't re-run.
"Need to explore first"Fine. Delete exploration, start with TDD.
"Test hard = code is fine"Test hard = design problem. Simplify.
"TDD slows me down"TDD faster than debugging.

Red Flags - STOP and Start Over

If you catch yourself:

  • Writing code before test
  • Test passing immediately
  • Can't explain why test failed
  • Rationalizing "just this once"
  • "Already manually tested it"
  • "Keep as reference" (delete means delete)

Delete the code. Start over with TDD.

Integration with Abilities

In /execute workflow:

Read task from phase file
       │
       ▼
Load /tdd skill
       │
       ├── RED: Write test for AC
       ├── Verify: Watch fail
       ├── GREEN: Implement minimal
       ├── Verify: Watch pass
       ├── REFACTOR: Clean up
       └── Commit
       │
       ▼
Load /subagent-review
       │
       ▼
Next task

Verification Checklist

Before marking task complete:

  • Test written BEFORE implementation
  • Watched test fail for correct reason
  • Wrote minimal code to pass
  • All tests passing
  • Output clean (no errors, warnings)
  • Tests use real code (minimal mocks)
  • Edge cases covered
  • Committed with descriptive message

Can't check all boxes? You skipped TDD. Start over.

The Bottom Line

Production code -> test exists and failed first
Otherwise -> not TDD

No exceptions.

Known Limitations and Deferred Work

  • TDD does not prove untested integration boundaries. See LIMITATIONS.md.

Keep looking

Skills are one crate of 627,801. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.