CtrlK
BlogDocsLog inGet started
Tessl Logo
SkillPublic

tdd

Use when implementing any feature or bugfix where correctness matters - before writing implementation code.

Quality

64%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide
SecuritybySnyk

Passed

No findings from the security scan

Fix and improve this skill with Tessl

tessl review fix ./skills/tdd/SKILL.md
SKILL.md
Quality
Evals
Security

/tdd - Test-Driven Development

Implement the feature using strict TDD methodology.

Target: $ARGUMENTS

When to Use

  • Implementing a new function, service, or module where correctness is critical
  • Fixing a bug that needs a regression test to prove it's fixed
  • Building business logic (calculations, validations, state machines)
  • When code handles money, auth, or sensitive data
  • Refactoring existing code that lacks test coverage
  • NOT for: quick prototypes or throwaway code
  • NOT for: pure UI layout changes with no logic
  • NOT for: configuration changes (env vars, build config)
  • NOT for: code that already has comprehensive tests (just add to existing suite)

Iron Law

╔══════════════════════════════════════════════════════════════╗
║  NO IMPLEMENTATION CODE WITHOUT A FAILING TEST FIRST         ║
╚══════════════════════════════════════════════════════════════╝

Workflow

Cycle Structure

For each behavior to implement:

┌───────┐      ┌───────┐      ┌──────────┐
│  RED  │ ───► │ GREEN │ ───► │ REFACTOR │
└───────┘      └───────┘      └──────────┘

Step 0: Detect Test Runner

Auto-detect the project's test runner before starting:

# Detect test runner from package.json or config files
if [ -f "vitest.config.ts" ] || [ -f "vitest.config.js" ] || grep -q '"vitest"' package.json 2>/dev/null; then
  TEST_CMD="npx vitest run"
  TEST_FILTER="--testNamePattern"
elif [ -f "jest.config.ts" ] || [ -f "jest.config.js" ] || grep -q '"jest"' package.json 2>/dev/null; then
  TEST_CMD="npx jest"
  TEST_FILTER="--testNamePattern"
elif [ -f "playwright.config.ts" ] || [ -f "playwright.config.js" ]; then
  TEST_CMD="npx playwright test"
  TEST_FILTER="--grep"
elif grep -q '"mocha"' package.json 2>/dev/null; then
  TEST_CMD="npx mocha"
  TEST_FILTER="--grep"
else
  TEST_CMD="npm test --"
  TEST_FILTER="--testNamePattern"
fi
echo "Test runner: $TEST_CMD"

Use the detected $TEST_CMD and $TEST_FILTER throughout all cycles.

Step 1: RED - Write Failing Test

  1. Create/open test file
  2. Write test for ONE behavior:
    it('should [expected behavior] when [condition]', () => {
      // Arrange
      const input = ...;
    
      // Act
      const result = functionUnderTest(input);
    
      // Assert
      expect(result).toBe(expected);
    });
  3. Run test:
    $TEST_CMD $TEST_FILTER="[test name]"
  4. Verify FAILS - Capture output showing failure
  5. BLOCKED if test passes (wrong test or code exists)

Step 2: GREEN - Minimal Implementation

  1. Write minimum code to pass:

    • No extra features
    • No optimization
    • Just enough to pass
  2. Run test:

    $TEST_CMD $TEST_FILTER="[test name]"
  3. Verify PASSES - Capture output showing success

  4. BLOCKED if test fails (fix before continuing)

Step 3: REFACTOR - Improve

  1. Improve code quality:

    • Remove duplication
    • Improve naming
    • Simplify logic
  2. Run ALL tests:

    $TEST_CMD
  3. Verify ALL PASS

  4. Check coverage change (if coverage tool is available):

    $TEST_CMD --coverage 2>/dev/null | grep -A 5 "Stmts\|Lines\|%" || true
  5. Commit cycle:

    git add -A && git commit -m "feat: [behavior] (TDD cycle N)"

Repeat

Continue cycles until feature is complete.

Verification Protocol

Every test run must be captured:

──── RED Phase ────
Test: should calculate discount for valid coupon
Running: npm test -- --testNamePattern="calculate discount"
Output:
  FAIL  src/discount.test.ts
  ✕ should calculate discount for valid coupon
    Expected: 90
    Received: undefined
Status: FAIL ✓ - Proceeding to GREEN

──── GREEN Phase ────
Running: npm test -- --testNamePattern="calculate discount"
Output:
  PASS  src/discount.test.ts
  ✓ should calculate discount for valid coupon
Status: PASS ✓ - Proceeding to REFACTOR

Output

──── /tdd ────
Feature: [name]

Cycle #1: [behavior]
  RED:      Test written, FAIL ✓
  GREEN:    Implemented, PASS ✓
  REFACTOR: Cleaned, PASS ✓

Cycle #2: [behavior]
  RED:      Test written, FAIL ✓
  GREEN:    Implemented, PASS ✓
  REFACTOR: Cleaned, PASS ✓

──── TDD Summary ────
Cycles completed: 2
Tests added: 2
All tests passing: ✓
Coverage: [if available]

Anti-Rationalization

ExcuseReality
"I know it works, no need to test first"Write the test. If it works, RED phase takes 30 seconds.
"This is too simple for TDD"Simple code has simple tests. No excuse to skip.
"I'll write tests after"Tests written after implementation verify your bias, not correctness.
"The test framework isn't set up"Set it up. That's part of the task.
"Just this once I'll skip RED""Just this once" is how every shortcut becomes a habit.
"The existing tests are enough"Enough for what? New behavior needs new tests. Existing tests verify old assumptions.
"I'll test the integration, not the unit"Integration tests verify wiring. Unit tests verify logic. You need both. Start with unit.

Rules

  1. Never implement before RED
  2. Capture all test output - Proof, not trust
  3. One behavior per test
  4. Minimal GREEN - Just enough to pass
  5. Always REFACTOR - Don't skip
  6. Document each cycle
Repository

fernandezbaptiste/specialist-agent

Path

skills/tdd/SKILL.md

Last updated
First committed

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.