tdd

hanayashiki's avatarfrom hanayashiki

Test-Driven Development workflow for packages/server. Write failing test first, then implement the fix.

0stars🔀0forks📁View on GitHub🕐Updated Jan 10, 2026

When & Why to Use This Skill

This Claude skill automates a rigorous Test-Driven Development (TDD) workflow specifically designed for server-side environments. By enforcing the 'Red-Green-Refactor' cycle, it ensures high code quality, minimizes regressions, and promotes maintainable software architecture through automated test execution and iterative implementation.

Use Cases

  • Feature Development: Implementing new server-side logic by first defining requirements through Vitest test cases to ensure the code meets all functional specifications from the start.
  • Bug Fixing and Regression Testing: Reproducing reported bugs by writing a failing test case first, then implementing the fix to ensure the issue is resolved and won't reappear in future builds.
  • Codebase Refactoring: Safely optimizing and cleaning up existing code in the packages/server directory while using the automated TDD loop to verify that no breaking changes are introduced.
  • API Validation: Ensuring new API endpoints or data validation logic correctly handle edge cases by writing comprehensive assertions before the actual implementation.
nametdd
descriptionTest-Driven Development workflow for packages/server. Write failing test first, then implement the fix.
user_invocabletrue
- Bash(pnpm test **)
- Bash(npm run test*)

TDD Workflow

This skill enforces Test-Driven Development for the packages/server package.

Workflow

1. Red: Write a Failing Test First

Before writing any implementation code, create or update a test file in packages/server/test/:

// Example test structure
import { describe, it, expect } from "vitest";
import dedent from "dedent";

describe("featureName", () => {
  it("should do the expected behavior", () => {
    // Arrange
    const input = ...;

    // Act
    const result = functionUnderTest(input);

    // Assert
    expect(result).toBe(expectedValue);
  });
});

Run the test to confirm it fails:

cd packages/server && pnpm test -- --run test/<test-file>.test.ts

The test MUST fail before proceeding. If it passes, the test is not testing new behavior.

2. Green: Write Minimal Implementation

Write the minimum code needed to make the test pass:

  • Only implement what's required to pass the test
  • Don't add extra features or optimizations
  • Don't refactor yet

Run the test again:

cd packages/server && pnpm test -- --run test/<test-file>.test.ts

The test MUST pass before proceeding.

3. Refactor: Clean Up the Code

Now that tests are green, improve the code:

  • Remove duplication
  • Improve naming
  • Simplify logic
  • Ensure consistent style

Run tests after each refactoring step to ensure nothing breaks:

cd packages/server && pnpm test

Test File Conventions

  • Test files: packages/server/test/*.test.ts
  • Use vitest with describe, it, expect
  • Use dedent for multi-line string fixtures
  • Import types from @openapi-lsp/core/openapi

Example TDD Session

Task: Add validation for empty arrays

Step 1 - Red:

it("should return error for empty array", () => {
  const result = validate([]);
  expect(result.ok).toBe(false);
  expect(result.error).toBe("Array cannot be empty");
});

Run test → FAIL ✗

Step 2 - Green:

function validate(arr: unknown[]) {
  if (arr.length === 0) {
    return { ok: false, error: "Array cannot be empty" };
  }
  return { ok: true };
}

Run test → PASS ✓

Step 3 - Refactor:

function validate(arr: unknown[]): Result<void, string> {
  if (arr.length === 0) {
    return Err("Array cannot be empty");
  }
  return Ok(undefined);
}

Run test → PASS ✓

Running Tests

# Run specific test file
cd packages/server && pnpm test -- --run test/serializeSchema.test.ts

# Run all tests
npm run test

# Run tests in watch mode (during development)
cd packages/server && pnpm test
tdd – AI Agent Skills | Claude Skills