From test-bdd
Generate BDD-style test files that document behavior with GIVEN/WHEN/THEN comments and test only public API and observable outcomes. Language and framework agnostic, with patterns and examples tuned for TypeScript + vitest + testing-library (hooks, components, utilities, constants).
How this skill is triggered — by the user, by Claude, or both
Slash command
/test-bdd:test-bddThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generate behavior-driven test files that focus on public API and observable behavior.
Generate behavior-driven test files that focus on public API and observable behavior.
setup.ts, vitest.config.ts, or existing test filesreferences/patterns.mdA single file rarely tells the full story: callers pass specific shapes, sibling files encode invariants, existing tests hint at conventions, and the bug that prompted the test may live in the git log. Before writing cases, spawn a subagent to gather that context and draft the case list.
Use the Explore agent (or general-purpose if deeper reasoning is needed)
via the Agent tool. Give it a self-contained brief that includes:
Ask the agent to report back using a BDD-native shape — the same
describe / context / it nesting with GIVEN/WHEN/THEN that the generated
test file will use. This keeps review cheap (the scenarios map 1:1 to the
code you're about to write) and keeps the skill internally consistent.
Prefer spec style (matches vitest / jest / RSpec output):
describe <unit under test>
context <condition, state, or collaborator setup>
it <expected observable behavior>
GIVEN ...
WHEN ...
THEN ...
[src/foo.ts:42 — `if (!user)` branch]
it ...
context ...
Open questions
- <ambiguity the agent couldn't resolve from the code>
Use Gherkin-style Feature / Scenario instead only if the project already
uses Cucumber or a Gherkin runner.
Notes for the agent's report:
context), not by a "happy / edge / error" bucket — BDD treats them
as a single flat list of scenarios.it with the code anchor that motivates it, so pruning is
reviewable. Prefer a stable anchor — a named branch or symbol
(`if (!user)` branch, split('?')) — over file:line; line
numbers drift even between the agent writing the report and you reading
it. This annotation lives in the report, to be reviewed and discarded.When the report comes back:
Only then move on to generating the test file.
Before generating anything, ask the user which level(s) of tests they want —
don't assume. Use AskUserQuestion (or a plain question if that tool isn't
available) with these choices, explained in terms of this file:
foo.test.ts and
foo.integration.test.ts) so they can run under different configs.Recommend a default based on the file:
| File kind | Default recommendation |
|---|---|
| Pure function / utility / constants | Unit |
| Hook / component with mockable deps | Unit |
| Repository / DB query / HTTP client | Integration |
| Router, workflow, or multi-module orchestrator | Both |
State the recommendation and why, but defer to the user's answer.
"Empty string / null / zero" is a starting list, not the finish line. Before writing cases, read the source carefully and derive edge cases from what the code actually does. Check each of these against the file in front of you:
undefined, NaN,
-0, very large, very small, unicode, trailing whitespace)?if, switch, ?., ??, try/catch,
early return. Each branch is an edge case worth naming.null, or returns an unexpected shape? Cover
the ones the code handles, and at least one it doesn't (to document
the contract).Only include cases that the code's behavior actually distinguishes. Don't pad the file with cases the implementation treats identically — one test per observable behavior.
Test public API and observable behavior only, never internal implementation:
Use BDD-style descriptions with flexible GIVEN/WHEN/THEN/AND comments:
// Full form
// GIVEN an unauthenticated user
// WHEN the protected route is accessed
// THEN the user should be redirected
// With AND for multiple assertions
// GIVEN a user is authenticated
// WHEN the profile page loads
// THEN the username should be displayed
// AND the avatar should be visible
// Simple form (no WHEN needed)
// GIVEN an empty array
// THEN length should be zero
// Multiple conditions
// GIVEN a valid token
// AND the user has admin role
// WHEN accessing admin panel
// THEN access should be granted
The motivating annotations from the agent's case-list report are for review
and pruning — by default keep them OUT of the committed test; the
GIVEN/WHEN/THEN already documents intent. Add an anchor only when an
assertion genuinely benefits from pointing at the code it locks in (e.g.
several sibling its each pin a different branch). When you do, use a
bare symbol or branch hint in brackets and nothing more:
// GIVEN a magic-link URL with the token in the query
// WHEN normalised
// THEN only the path survives
// [split('?')]
Never put a file:line in a committed test — the line goes stale on the
next edit above it and silently misleads. Drop the filename too when the
test is co-located with the unit it imports; it's redundant.
catch, rejection, or
fallback branch in the source)references/patterns.md - Detailed test patterns and mock handlingreferences/examples.md - Complete example test files2plugins reuse this skill
First indexed Jun 30, 2026
npx claudepluginhub guillempuche/ai-skill-test-bdd --plugin test-bddGuides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.