Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Test Driven Development

ASecurity

Write tests before code; reproduce bugs before fixing them. Use when implementing logic, fixing bugs, or modifying behavior. Tests are proof — "seems right" isn't done.

33 stars
0 votes
0 copies
0 views
Added 9/20/2026
testingtypescriptrustgosqltestingapi

Works with

api

Security Analysis

A100/100

Scanned 9/20/2026

Install to Claude Code

$npx -y skills add ayunis-core/ayunis-core --skill test-driven-development --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Test Driven Development?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Test Driven Development
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/ayunis-core-test-driven-development/badge)](https://www.skillsdirectory.com/skills/ayunis-core-test-driven-development)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
name: test-driven-development
description: Write tests before code; reproduce bugs before fixing them. Use when implementing logic, fixing bugs, or modifying behavior. Tests are proof — "seems right" isn't done.
---

# Test-Driven Development

Write a failing test before writing the code that makes it pass. For bug fixes, reproduce the bug with a test before attempting a fix. A codebase with good tests is an agent's superpower; a codebase without tests is a liability.

## When to use

- Implementing new logic or behavior
- Fixing a bug (use the Prove-It pattern below)
- Modifying existing functionality
- Adding edge case handling
- Any change that could break existing behavior

**When NOT to use:** pure config changes, doc updates, static content with no behavioral impact.

## The cycle: Red → Green → Refactor

1. **Red** — Write a test that fails. A test that passes immediately proves nothing.
2. **Green** — Write the minimum code to make it pass. Don't over-engineer.
3. **Refactor** — Clean up with tests still green. Run tests after every refactor step.

Repeat. One concept at a time.

## The Prove-It pattern (bug fixes)

When a bug is reported, **don't start by trying to fix it**. Start by writing a test that reproduces it.

1. Write a test that demonstrates the bug. It must fail.
2. The failing test confirms the bug exists and that you understand it.
3. Implement the fix.
4. The test now passes — fix proven, regression guarded.
5. Run the additional validation required by the repository's Proportional Workflow and the applicable surface-specific skill.

If you can't write a failing test for the bug, you don't understand the bug yet. Stop and figure it out before touching the code.

## The test pyramid

Distribute testing effort by level:

```txt
        ╱╲
       ╱E2E╲          ~5% — full user flows, real browser
      ╱─────╲
     ╱integ. ╲        ~15% — boundaries, API, DB
    ╱────────╲
   ╱   unit   ╲       ~80% — pure logic, isolated, ms each
  ╱────────────╲
```

**The Beyonce Rule:** if you liked it, you should have put a test on it. Refactors don't catch your bugs — your tests do. Untested code that breaks is on you.

## Test sizes

Classify by what the test consumes:

| Size       | Constraints                               | Speed   | Where                              |
| ---------- | ----------------------------------------- | ------- | ---------------------------------- |
| **Small**  | Single process, no I/O, no DB, no network | ms      | Pure logic, transforms, validators |
| **Medium** | Localhost only, no external services      | seconds | API + test DB, components          |
| **Large**  | External services allowed                 | minutes | E2E, perf, staging integration     |

The vast majority of the suite should be small. They're fast, reliable, and easy to debug.

## Writing good tests

### Test state, not interactions

Assert on the _outcome_ of the operation, not on which methods were called internally. Interaction-based tests break on every refactor even when behavior is unchanged.

```typescript
// Good — tests behavior
const tasks = await listTasks({ sortBy: "createdAt", sortOrder: "desc" });
expect(tasks[0].createdAt.getTime()).toBeGreaterThan(
  tasks[1].createdAt.getTime(),
);

// Bad — tests SQL string
expect(db.query).toHaveBeenCalledWith(
  expect.stringContaining("ORDER BY created_at DESC"),
);
```

### DAMP over DRY in tests

In production code, DRY is usually right. In tests, **DAMP** (Descriptive And Meaningful Phrases) wins. Each test should read like a specification — self-contained, no tracing through shared helpers to figure out what's being verified. Duplication in tests is acceptable when it makes each test independently understandable.

### Prefer real implementations

Use the simplest test double that gets the job done. The closer to real, the more confidence:

```txt
Real implementation > Fake (in-memory) > Stub (canned data) > Mock (interaction)
```

Mock only when the real implementation is too slow, non-deterministic, or has side effects you can't control (external APIs, email sending). Over-mocking creates tests that pass while production breaks.

### Arrange-Act-Assert

```typescript
it("marks tasks overdue when deadline has passed", () => {
  // Arrange
  const task = createTask({ title: "Test", deadline: new Date("2025-01-01") });
  // Act
  const result = checkOverdue(task, new Date("2025-01-02"));
  // Assert
  expect(result.isOverdue).toBe(true);
});
```

### One assertion per concept

Each test verifies one behavior. Names read like a spec.

```typescript
// Good
it('rejects empty titles', ...);
it('trims whitespace from titles', ...);
it('enforces maximum title length', ...);

// Bad
it('validates titles correctly', () => {
  // ten different things in one test
});
```

## Anti-patterns

| Anti-pattern                   | Why it hurts                            | Fix                                      |
| ------------------------------ | --------------------------------------- | ---------------------------------------- |
| Testing implementation details | Tests break on every refactor           | Test inputs and outputs                  |
| Flaky tests (timing, ordering) | Erodes trust in the suite               | Deterministic assertions, isolated state |
| Testing framework code         | Wastes effort                           | Only test YOUR code                      |
| Snapshot abuse                 | Nobody reviews, breaks on any change    | Use sparingly, review every change       |
| No test isolation              | Pass alone, fail together               | Per-test setup/teardown                  |
| Mocking the unit under test    | Tests prove nothing about real behavior | Mock dependencies, never the subject     |

## Common rationalizations

| Rationalization                                           | Reality                                                                                                                          |
| --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| "I'll write tests after the code works."                  | You won't. And post-hoc tests test the implementation you wrote, not the behavior you needed.                                    |
| "This is too simple to test."                             | Simple code gets complicated. The test documents the expected behavior for the next person.                                      |
| "Tests slow me down."                                     | Tests slow you down now. They speed you up every time you change the code later.                                                 |
| "I tested it manually."                                   | Manual testing doesn't persist. Tomorrow's refactor breaks it with no way to know.                                               |
| "The code is self-explanatory."                           | Tests _are_ the spec. They describe what the code should do, not what it currently does.                                         |
| "It's just a prototype."                                  | Prototypes become production. Tests from day one avoid the test-debt crisis.                                                     |
| "I'll add the bug-reproduction test after I've fixed it." | If you fix first, the test only verifies your assumption about the fix, not the original bug. The test must fail before the fix. |
| "All tests pass."                                         | Did you actually run them? "All tests pass" with no command output is the agent equivalent of "trust me." Show the output.       |
| "This test is too hard to write — let me skip it."        | Hard-to-test code is a design smell. The friction is signal, not noise. Restructure the code so it can be tested.                |

## Red flags

- Writing code without a corresponding test
- Tests that pass on the first run (verify they actually fail when you break the code under test)
- Bug fixes without a reproduction test that failed before the fix
- Test names that don't describe a behavior ("works", "handles errors", "test 3")
- Skipping or disabling tests to make the suite pass
- Mocking the unit under test
- "All tests pass" without producing the test runner's output

## Verification

After implementation:

- [ ] Every new behavior has a corresponding test
- [ ] All tests required by the Proportional Workflow pass — and the test runner's output proves it
- [ ] Bug fixes include a reproduction test that failed before the fix
- [ ] Test names describe behavior, not implementation
- [ ] No skipped or disabled tests
- [ ] Coverage hasn't decreased (if tracked)

Attribution

ayunis-coreayunis-core
View sourceMore from ayunis-core →
SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

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 (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Your tool, in front of Claude Code builders.

3 founder slots · $299/mo · GSC-verified traffic · sponsors can never buy grades.

See placements

Related Skills

Screen Reader Testing

Practical guide to testing web applications with screen readers for comprehensive accessibility validation.

397921 votes

Eval Harness

克劳德代码会话的正式评估框架,实施评估驱动开发(EDD)原则

2456590 votes

Tdd Workflow

在编写新功能、修复错误或重构代码时使用此技能。强制执行测试驱动开发,包含单元测试、集成测试和端到端测试,覆盖率超过80%。

2456590 votes

Springboot Tdd

使用JUnit 5、Mockito、MockMvc、Testcontainers和JaCoCo进行Spring Boot的测试驱动开发。适用于添加功能、修复错误或重构时。

2456590 votes

Python Testing

使用pytest、TDD方法、夹具、模拟、参数化和覆盖率要求的Python测试策略。

2456590 votes
View all in testing →