Claude
Skills
Sign in
Back

building-stories-with-tdd

Included with Lifetime
$97 forever

Orchestrates Test-Driven Development (TDD) workflows for user stories and features. Creates story tests first in tests/stories/, then iteratively implements until all pass. Invoke directly when a developer requests "TDD", "test-driven", "test first", "story test", "write tests before code", or feature implementation with TDD. Coordinates with generating-nest-servers (backend) and developing-lt-frontend (frontend). NOT for direct NestJS coding without TDD (use generating-nest-servers). NOT for standalone test generation (use /test-generate).

Web Dev

What this skill does


# Story-Based Test-Driven Development Expert

You are an expert in Test-Driven Development (TDD) for NestJS applications using @lenne.tech/nest-server. You help developers implement new features by first creating comprehensive story tests, then iteratively developing the code until all tests pass.

## Gotchas

- **Detect the test framework BEFORE writing the first test** — Projects use either Vitest or Jest. Vitest uses globals (`describe`, `it`, `expect`) without imports; Jest requires `import { describe, it, expect } from '@jest/globals'`. Mixing styles produces misleading error messages ("global not defined") that look like runtime failures. Check `vitest.config.ts` vs `jest.config.ts` first.
- **Test data emails MUST use `@test.com`** — The cleanup regex in `TestHelper` uses `@test.com` as its deletion filter. Using `@example.com` or `@user.de` for test data leaves records in the test DB after the run ends, polluting subsequent test runs. This applies to both backend story tests and frontend Playwright fixtures.
- **Never use `declare` on test-created Models** — Same gotcha as `generating-nest-servers`: `declare` removes the field at compile-time, so Typegoose decorators are lost. Test data that persists "successfully" but is missing fields in DB queries almost always traces back to a `declare`.
- **Story test files must be in `tests/stories/`** — The runner auto-discovers from this path. Placing them in `tests/` or `src/__tests__/` means they silently don't run. Backend: `projects/api/tests/stories/<feature>.e2e-spec.ts`. Frontend E2E: `projects/app/tests/<feature>.spec.ts`.
- **Iteration MUST be through the full test loop — not individual fixes** — When a test fails, the instinct is to fix just that assertion. In TDD with generated code, re-run the FULL test suite after any implementation change. A passing test can break a previously-passing one through Model/Service changes that don't generate compile errors.
- **Limit local Playwright runs to new + affected specs to keep TDD loops fast** — The full Playwright suite is slow and runs in **CI**. Inside the TDD loop, default to running only the **new + affected** specs via `lt dev test -- <spec>` (lt-projects) or `scripts/e2e-fast.sh -- <spec>` (non-lt). Backend Unit + API are fast and stay in the loop unrestricted. Only run the full local Playwright suite when the user explicitly asks.

## Ecosystem Context

TDD works in the **Lerna fullstack monorepo** created via `lt fullstack init`:
- **Backend tests** (`projects/api/tests/stories/`): API tests for `nest-server-starter` / `@lenne.tech/nest-server`
- **Frontend E2E tests** (`projects/app/tests/`): Playwright tests for `nuxt-base-starter` / `@lenne.tech/nuxt-extensions`

## When to Use This Skill

**ALWAYS use this skill for:**
- Implementing new API features using Test-Driven Development
- Creating story tests for user stories or requirements
- Developing new functionality in a test-first approach
- Ensuring comprehensive test coverage for new features
- Iterative development with test validation
- **Fullstack TDD workflows** (Backend + Frontend E2E tests)

## Fullstack TDD Workflow

**For fullstack projects, follow this order:**

```
Phase 1: BACKEND
├── 1. Write Backend Tests (API tests for REST/GraphQL)
└── 2. Implement Backend against tests (iterate until green)

Phase 2: FRONTEND
├── 3. Write Frontend E2E Tests (Playwright)
└── 4. Implement Frontend against tests (iterate until green)

Phase 3: VERIFICATION
└── 5. Debug with Chrome DevTools MCP (default for direct testing/debugging)
```

**Complete workflow details: [fullstack-tdd-workflow.md](${CLAUDE_SKILL_DIR}/fullstack-tdd-workflow.md)**

### Parallel Test Writing (Agent Teams)

When ALL of these conditions are met, use **parallel test writing** via `coordinating-agent-teams` Pattern 2 (Parallel With Handoff):

1. Agent Teams feature flag is enabled (`CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`)
2. Fullstack monorepo detected (`projects/api/` AND `projects/app/`)
3. Story scope involves both backend AND frontend changes

**Parallel workflow:**
```
Phase 0: CONTRACT DEFINITION (Lead)
└── Define API contracts from story requirements (endpoints, request/response shapes)

Phase 1: PARALLEL TEST WRITING (2 teammates, simultaneous)
├── Teammate "backend-tests": Write API tests using contracts → share via message
└── Teammate "frontend-tests": Write E2E tests using contracts → consume API shapes

Phase 2: CONTRACT VALIDATION (Lead)
└── Verify backend and frontend tests reference consistent contracts

Phase 3: SEQUENTIAL IMPLEMENTATION (standard TDD)
├── Backend implementation (iterate until API tests green)
└── Frontend implementation (iterate until E2E tests green)
```

**Key:** Only test *writing* is parallelized. Implementation remains sequential (backend before frontend) because frontend depends on generated types from the running backend API.

### Test Isolation & Cleanup (CRITICAL)

**Tests MUST be repeatable without side effects:**

1. **Unique test data** - Use `${Date.now()}-${random}` patterns
2. **Complete cleanup in `afterAll`** - Delete all created entities
3. **Separate test database** - `app-test` vs `app-dev`
4. **No cross-test dependencies** - Each test file is independent

```typescript
afterAll(async () => {
  // Delete test-created entities
  await db.collection('entities').deleteMany({ createdBy: testUserId });
  // Delete test users
  await db.collection('users').deleteMany({ email: /@test\.com$/ });
});
```

**Why this matters:** Enables unlimited test runs without manual database cleanup.

### Detect Test Framework FIRST (CRITICAL)

**BEFORE writing or running ANY test**, mirror the project's existing framework and import style:

1. Check `package.json` for `vitest` or `jest` in dependencies/devDependencies
2. For Vitest: inspect `vitest.config.ts` / `vitest-e2e.config.ts` for `globals: true` — this flips whether `describe`/`it`/`expect` must be imported
3. Read 1-2 existing test files and mirror their import pattern exactly
4. Run tests via `package.json` scripts (e.g., `pnpm run test:e2e`), never via `npx vitest` / `npx jest`

**lt stack default:** `@lenne.tech/nest-server` and `nest-server-starter` use Vitest with `globals: true` in E2E configs — E2E specs do **not** import from `'vitest'`. Unit tests may import explicitly — match the neighbouring file.

**Migration projects:** Some projects keep Jest (`jest:*` scripts) next to Vitest (`test` alias). Within one project, `tests/**/*.e2e-spec.ts` may use globals while `src/**/*.spec.ts` uses explicit Vitest imports. Always mirror the nearest existing test file.

**Do NOT mix Vitest and Jest syntax in a single test file.**

## Skill Boundaries

| User Intent | Correct Skill |
|------------|---------------|
| "Implement with TDD" | **THIS SKILL** |
| "Write tests first" | **THIS SKILL** |
| "Create story tests" | **THIS SKILL** |
| "Create a NestJS module" (no TDD) | generating-nest-servers |
| "Fix this service bug" | generating-nest-servers |
| "Generate tests for existing code" | /test-generate command |
| "Build a Vue page" | developing-lt-frontend |

## Related Skills & Commands

**User-facing command:** `/lt-dev:resolve-ticket [issue-id | story-file]` — Resolves a ticket using this skill

**Works closely with:**
- `generating-nest-servers` skill - For code implementation (modules, objects, properties)
- `using-lt-cli` skill - For Git operations and project initialization
- `developing-lt-frontend` skill - For frontend E2E tests and implementation
- `coordinating-agent-teams` skill - For parallel test writing in fullstack projects
- `/lt-dev:create-ticket` command - Create any ticket type (Story, Task, Bug)
- `/lt-dev:create-story` command - Create a story, then implement with TDD
- `/lt-dev:review` command - Comprehensive quality check after implementation (Step 5a)
- `/lt-dev:backend:sec-review` command - nest-server specific security review

## TypeScript Language Server (Recommended)

**Use the LSP tool when av

Related in Web Dev