Skip to content
Back to skills

Tdd

ASecurity

Test-Driven Development skill. Guides writing tests before implementation — test-first workflow, co-located test files, and boundary mocking. Enforces Red-Green-Refactor cycle.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 19, 2026
ai-agentstypescriptshellbashapisecurity

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 19, 2026

npx -y skills add dustinkeeton/wafflestack --skill tdd --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Tdd?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Tdd
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/dustinkeeton-tdd/badge)](https://www.skillsdirectory.com/skills/dustinkeeton-tdd)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: tdd
description: Test-Driven Development skill. Guides writing tests before implementation — test-first workflow, co-located test files, and boundary mocking. Enforces Red-Green-Refactor cycle.
user-invocable: true
---

# Test-Driven Development (TDD)

When this skill is invoked, follow the TDD workflow below. If invoked with arguments (e.g., `/tdd src/shared/validation.ts`), scope the work to that file or module. If invoked without arguments, audit the codebase for missing test coverage and propose a plan.

## How and when to use

Reach for TDD whenever you are about to change behavior:

- **New source files** — write the test first. Before a new function, class, or module exists, write a failing test that pins the behavior you intend, then implement against it (the Red-Green-Refactor cycle below).
- **Bug fixes** — reproduce before you repair. Write a failing **regression test** that captures the bug first, watch it fail, then fix the code until it passes. The test stays behind as a guard against the bug returning.
- **Refactors** — lean on the existing tests as a safety net. If the code you are about to restructure has no tests, add them first so the refactor is verifiable.

This skill is both **user-invocable** and **agent-granted**:

- **User-invoked** — run `/tdd <path>` to scope the workflow to a file or module (e.g. `/tdd src/shared/validation.ts`), or `/tdd` with no argument to audit the codebase for missing coverage and propose a plan.
- **Agent-granted** — agents that list `tdd` in their `skills:` frontmatter follow this workflow automatically when writing new code or fixing bugs, without an explicit invocation.

## Framework & Structure

- **Test runner:** the project's standard runner — `{{project.testCmd}}` runs the suite
- **Test files:** Co-located next to source as `<name>.test.<ext>` (e.g., `src/shared/validation.test.ts`)
- **Test utilities:** a central test-utils directory (e.g., `src/__test-utils__/`) — mock factories, fixtures, helpers

## Red-Green-Refactor Cycle

When implementing a new function, class, or feature:

1. **RED** — Write a failing test first. Run the runner scoped to that file (most runners accept a path argument) to confirm it fails.
2. **GREEN** — Write the minimum implementation to make the test pass.
3. **REFACTOR** — Clean up both test and production code. Run tests again to confirm they still pass.

Every new source file must have a corresponding test file, unless it is:
- A type-only file (`types.ts`)
- A re-export barrel (`index.ts` that only re-exports)
- A thin UI shell over host-application base classes (test these indirectly through their callers, or extract testable logic into pure functions)

## Test Priority Tiers

{{tdd.priorityTiers}}

## Test Quality Rules

1. **Arrange-Act-Assert** — Every test follows AAA with clear separation.
2. **Descriptive names** — `it('returns null when file is in excluded folder')`, not `it('test 1')`.
3. **One behavior per test** — Multiple assertions OK only when verifying facets of the same behavior.
4. **No test interdependence** — Each test sets up its own fixtures. No shared mutable state.
5. **Mock at the boundary** — Mock external dependencies (network clients, `child_process`, host-application APIs), not internal functions. If you need to mock an internal function, refactor to inject the dependency.
6. **No real API calls** — Tests must never hit real network endpoints. Mock all HTTP.
7. **Security functions get exhaustive coverage** — sanitizers and validators (e.g., `sanitizeUrl`, `sanitizePath`) must test: null bytes, path traversal, shell metacharacters, non-HTTP schemes, XSS vectors, and each pattern the sanitizer strips.

## Mocking Patterns

Examples use Vitest-style APIs (`vi`); adapt to the project's runner.

### Module mocks and factories
Mock host-application or platform modules centrally (a `__mocks__/` directory the runner auto-loads) so every test consumes the same stubs. Keep per-object mock factories in the test-utils directory — fresh instance per test, override-friendly defaults.

### Mocking global `fetch`
```typescript
beforeEach(() => { global.fetch = vi.fn(); });
afterEach(() => { vi.restoreAllMocks(); });
```

### Mocking `child_process`
```typescript
vi.mock('child_process', () => ({
  execFile: vi.fn((cmd, args, opts, cb) => cb(null, '{}', '')),
}));
```

## Architectural Test Rules

1. {{tdd.moduleBoundaries}}
2. **Settings immutability** — Tests should pass frozen settings and verify no mutations.

## Running Tests

```bash
{{project.testCmd}}   # full suite
```

Use the runner's watch and coverage modes during development where available.

## TDD Workflow for New Features

{{tdd.workflows}}

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…