test-writer
Skill6 starsChanged 8 months agoMITView on GitHub
Use this skill when writing unit tests, integration tests, or end-to-end tests for existing or new code. Trigger phrases: 'write tests for', 'add test coverage', 'how do I test this', 'TDD this feature'. Not for running or debugging test infrastructure or CI pipelines.
28 other projects use a version of this.
Adopted by
Most recently taken up by
- seankoji-com/.agentstheir own version, first seen Nov 8, 2026
- Devolutions/IronRDPtheir own version, first seen Nov 1, 2026
- WST2002/claude-code-skillstheir own version, first seen Oct 17, 2026
- anchildress1/awesome-aitheir own version, first seen Oct 13, 2026
- krishnamallam/upboxtheir own version, first seen Oct 11, 2026
- poshan0126/dotclaudetheir own version, first seen Oct 8, 2026
Used with
Projects with it also use debug-fix, changelog-writer and 8 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
zebbernSkilldebug-fix
Find and fix a bug or issue — from any source (GitHub issue, error message, user report, or observed behavior)
Also in 4 projects that use this
zbruhnkeSkillchangelog-writer
Maintain CHANGELOG.md with properly categorized entries. Use after implementing features, fixing bugs, or making any notable changes. Follows Keep a Changelog format.
Also in 5 projects that use this
glinckerSkillreadme-generator
Generates comprehensive README.md files for software projects by analyzing codebase structure
Also in 4 projects that use this
get-proofpilotSkillcontext-budget
Audits Claude Code context window consumption across agents, skills, MCP servers, and rules. Identifies bloat, redundant components, and produces prioritized token-savings recommendations.
Also in 3 projects that use this
nimbalystSkillprd-writer
Create structured Product Requirements Documents (PRDs) with prioritized requirements. Use when writing product specs, feature requirements, or project briefs.
Also in 3 projects that use this
GitHubSkillrefactor
Surgical code refactoring to improve maintainability without changing behavior. Covers extracting functions, renaming variables, breaking down god functions, improving type safety, eliminating code smells, and applying design patterns. Less drastic than repo-rebuilder; use for gradual improvements.
Also in 4 projects that use this
Other versions28 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 28
- leonardomso/33-js-concepts★ 67ksame name
- Devolutions/IronRDP★ 3.3ksame name
- poshan0126/dotclaude★ 871same name
- TheDecipherist/claude-code-mastery-project-starter-kit★ 337same name
- hamzafarooq/claude-code-starter★ 145same name
- anchildress1/awesome-ai★ 67same name
- anchildress1/awesome-github-copilot★ 67same name
- nimbalyst/skills★ 28same name
- Twigpine/openclaude-skills★ 19same name
- jeremymcs/skills★ 8same name
18 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository68 other files it gives its agents.
- dataset-curatorSkill
- eval-designerSkill
- model-comparatorSkill
- prompt-engineerSkill
- business-analystSkill
- competitor-analystSkill
- market-researcherSkill
- meeting-facilitatorSkill
- okr-plannerSkill
- pitch-deck-writerSkill
- product-managerSkill
- ux-researcherSkill
- api-designerSkill
- architecture-designerSkill
- code-reviewerSkill
- debuggerSkill
- documentation-writerSkill
- refactorerSkill
- regex-masterSkill
- security-auditorSkill
- sql-expertSkill
- chart-builderSkill
- dashboard-designerSkill
- data-analystSkill
- data-cleanerSkill
- excel-expertSkill
- sql-analystSkill
- color-paletteSkill
- design-critiquerSkill
- frontend-designSkill
- ux-writerSkill
- ci-cd-helperSkill
- docker-expertSkill
- kubernetes-helperSkill
- monitoring-setupSkill
- flashcard-makerSkill
- lesson-plannerSkill
- quiz-creatorSkill
- tutorSkill
- docxSkill
- pdfSkill
- pptxSkill
- xlsxSkill
- budget-plannerSkill
- financial-analystSkill
- invoice-generatorSkill
- contract-reviewerSkill
- legal-summarizerSkill
- terms-of-serviceSkill
- decision-makerSkill
- habit-builderSkill
- journalingSkill
- note-takerSkill
- task-plannerSkill
- citation-formatterSkill
- fact-checkerSkill
- literature-reviewerSkill
- summarizerSkill
- web-researcherSkill
- academic-essaySkill
- The first 60 shown.
The file
Show its rules and text
We split this skill into the rules it gives an agent
17 rules. 0 are common, 14 are distinctive, and 3 are very specific to this project.
0
Common
Most of the 27 edited versions we read keep these.
14
Distinctive
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 51
Unit test: test a function in isolation with all dependencies mocked.
- Distinctive: line 52
Integration test: test multiple real components together (e.g., service + real DB).
- Distinctive: line 53
E2E test: test a full user-facing workflow through the actual UI or API.
- Very specific: line 71
Test file: co-locate with source or mirror directory structure: utils.test.ts, utils.spec.py
- Distinctive: line 75
Do NOT mock the thing you're testing.
- Distinctive: line 76
Do NOT mock value objects or pure functions — use real instances.
- Distinctive: line 77
Prefer dependency injection over module-level patching for testability.
- Distinctive: line 81
Verify side effects: was the correct database method called with the correct args?
- Distinctive: line 83
Avoid asserting on internal implementation details that could change without breaking behavior.
- Distinctive: line 86
Run coverage report; target 80%+ line coverage on business logic.
- Distinctive: line 247
Write tests before code (TDD) to drive better API design
- Distinctive: line 250
Keep tests fast — slow tests don't get run.
- Distinctive: line 251
Use test factories or builders for complex object setup to avoid repetition
- Distinctive: line 252
Test the contract (what), not the implementation (how) — brittle tests couple to internals
- Distinctive: line 256
Not testing error paths and edge cases — happy-path-only tests miss most bugs
- Very specific: line 263
Use test.each (Jest) or @pytest.mark.parametrize for table-driven tests with multiple input/output pairs
- Very specific: line 266
Use faker or factory-boy to generate realistic test data instead of hand-crafting fixtures
“Common” is measured: kept by at least 6 in 10 of the 27 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Test Writer
Overview
The Test Writer skill produces comprehensive, maintainable tests following established practices: the test pyramid (unit → integration → e2e), the AAA (Arrange-Act-Assert) pattern, meaningful naming conventions, and effective mocking strategies. It helps determine what to test, how to structure test files, what to mock vs. not mock, and how to set coverage targets. Good tests serve as executable documentation that catches regressions before they reach production.
When to Use
- Writing tests for a new function, class, or module
- Adding tests to untested legacy code before refactoring
- Following Test-Driven Development (TDD) — writing tests before implementation
- Evaluating test coverage and identifying what's missing
- Writing integration tests for API endpoints or database interactions
When NOT to Use
- Setting up CI/CD pipelines or test runners (infrastructure concern)
- Load testing or performance benchmarking (different tooling)
- Writing end-to-end browser automation scripts (use a Playwright/Cypress skill)
- Debugging a failing test (use the debugger skill to find the root cause)
Quick Reference
| Level | Scope | Speed | Mock? | Target % |
| Unit | Single function/class | Fast (<1ms) | Dependencies | 70–80% of tests |
| Integration | Multiple modules + real DB/API | Medium (10–100ms) | External services only | 15–25% of tests |
| E2E | Full user journey through UI | Slow (1–30s) | Nothing | 5–10% of tests |
| Concept | Description |
| AAA | Arrange (set up) → Act (call) → Assert (verify) |
| Naming | describe('unit') / it('should behavior when condition') |
| Mocking | Replace dependencies with controlled test doubles |
| Coverage target | 80% line coverage; 100% on critical paths |
| TDD cycle | Red → Green → Refactor |
Instructions
- Identify the unit under test
- Pick a single function, method, or class as the subject.
- List all inputs, outputs, side effects, and error conditions.
- Identify dependencies that need to be mocked (databases, HTTP clients, file system, clocks).
- Choose the right test level
- Unit test: test a function in isolation with all dependencies mocked.
- Integration test: test multiple real components together (e.g., service + real DB).
- E2E test: test a full user-facing workflow through the actual UI or API.
- Identify test cases
- Happy path: the function works correctly with valid input.
- Edge cases: empty string, empty array, zero, null, very large numbers, boundary values.
- Error cases: invalid input, dependency throws, timeout.
- State variations: first-time user vs. returning user; empty list vs. full list.
- Apply the AAA pattern to each test
// Arrange — set up test data and mocks // Act — call the function under test // Assert — verify the output or side effects - Apply naming conventions
- Describe block: name of the unit under test —
describe('calculateDiscount') - It block: "should [expected behavior] when [condition]" —
it('should return 0 when cart is empty') - Test file: co-locate with source or mirror directory structure:
utils.test.ts,utils.spec.py
- Describe block: name of the unit under test —
- Mock strategically
- Mock I/O boundaries: databases, HTTP calls, file system, time, random.
- Do NOT mock the thing you're testing.
- Do NOT mock value objects or pure functions — use real instances.
- Prefer dependency injection over module-level patching for testability.
- Assert precisely
- Assert on the exact expected value, not just that "something was called."
- Verify side effects: was the correct database method called with the correct args?
- For error cases: assert the exact error type and message.
- Avoid asserting on internal implementation details that could change without breaking behavior.
- Check coverage
- Run coverage report; target 80%+ line coverage on business logic.
- 100% coverage on security-critical paths (auth, payment, data validation).
- Untested branches show up as risk — prioritize covering error paths.
Examples
Example 1: Write unit tests for a utility function (JavaScript/Jest)
Input: A calculateDiscount function to test:
// discount.js
export function calculateDiscount(price, userTier) {
if (price <= 0) throw new Error('Price must be positive');
const rates = { silver: 0.05, gold: 0.10, platinum: 0.20 };
const rate = rates[userTier] ?? 0;
return Math.round(price * rate * 100) / 100;
}Output:
// discount.test.js
import { calculateDiscount } from './discount';
describe('calculateDiscount', () => {
describe('happy path', () => {
it('should apply 5% discount for silver tier', () => {
// Arrange
const price = 100;
const tier = 'silver';
// Act
const result = calculateDiscount(price, tier);
// Assert
expect(result).toBe(5.00);
});
it('should apply 10% discount for gold tier', () => {
expect(calculateDiscount(100, 'gold')).toBe(10.00);
});
it('should apply 20% discount for platinum tier', () => {
expect(calculateDiscount(100, 'platinum')).toBe(20.00);
});
it('should return 0 discount for unknown tier', () => {
expect(calculateDiscount(100, 'bronze')).toBe(0);
});
it('should return 0 discount when tier is undefined', () => {
expect(calculateDiscount(100, undefined)).toBe(0);
});
it('should round to 2 decimal places', () => {
// $99.99 * 5% = 4.9995 → rounds to 5.00
expect(calculateDiscount(99.99, 'silver')).toBe(5.00);
});
});
describe('error cases', () => {
it('should throw when price is zero', () => {
expect(() => calculateDiscount(0, 'gold')).toThrow('Price must be positive');
});
it('should throw when price is negative', () => {
expect(() => calculateDiscount(-50, 'gold')).toThrow('Price must be positive');
});
});
describe('edge cases', () => {
it('should handle very small positive price', () => {
expect(calculateDiscount(0.01, 'platinum')).toBe(0.00);
});
it('should handle very large price', () => {
expect(calculateDiscount(1_000_000, 'platinum')).toBe(200_000);
});
});
});Example 2: Write an integration test for an API endpoint (Node.js/Jest + Supertest)
Input: An Express endpoint to test:
// routes/users.js
router.post('/users', async (req, res) => {
const { email, name } = req.body;
if (!email) return res.status(422).json({ error: 'email is required' });
const existing = await db.users.findByEmail(email);
if (existing) return res.status(409).json({ error: 'email already in use' });
const user = await db.users.create({ email, name });
return res.status(201).json(user);
});Output:
// routes/users.integration.test.js
import request from 'supertest';
import { app } from '../app';
import { db } from '../db';
// Use a real test database — no mocking of db layer
beforeAll(async () => { await db.migrate.latest(); });
afterAll(async () => { await db.destroy(); });
afterEach(async () => { await db.raw('DELETE FROM users'); }); // clean state
describe('POST /users', () => {
describe('successful creation', () => {
it('should create a user and return 201 with user data', async () => {
// Arrange
const payload = { email: 'alice@example.com', name: 'Alice' };
// Act
const res = await request(app).post('/users').send(payload);
// Assert
expect(res.status).toBe(201);
expect(res.body).toMatchObject({
id: expect.any(String),
email: 'alice@example.com',
name: 'Alice',
createdAt: expect.any(String),
});
// Verify persisted to DB
const saved = await db.users.findByEmail('alice@example.com');
expect(saved).not.toBeNull();
});
});
describe('validation errors', () => {
it('should return 422 when email is missing', async () => {
const res = await request(app).post('/users').send({ name: 'Bob' });
expect(res.status).toBe(422);
expect(res.body.error).toBe('email is required');
});
});
describe('conflict errors', () => {
it('should return 409 when email already exists', async () => {
// Arrange — seed an existing user
await db.users.create({ email: 'carol@example.com', name: 'Carol' });
// Act
const res = await request(app)
.post('/users')
.send({ email: 'carol@example.com', name: 'Carol 2' });
// Assert
expect(res.status).toBe(409);
expect(res.body.error).toBe('email already in use');
});
});
});Best Practices
- Write tests before code (TDD) to drive better API design
- One logical assertion concept per test — multiple
expect()calls are fine if they verify the same behavior - Tests should be deterministic: no random data, no time-dependent behavior (mock
Date.now()) - Keep tests fast — slow tests don't get run; unit tests should complete in milliseconds
- Use test factories or builders for complex object setup to avoid repetition
- Test the contract (what), not the implementation (how) — brittle tests couple to internals
Common Mistakes
- Testing implementation details (private methods, internal state) instead of observable behavior
- Not testing error paths and edge cases — happy-path-only tests miss most bugs
- Over-mocking: mocking so much that tests pass even when real integrations are broken
- Using production database in tests without cleanup — tests pollute each other
- Testing framework code (e.g., testing that Express routing works) instead of your business logic
- Ignoring flaky tests — a flaky test is worse than no test (false confidence)
Tips & Tricks
- Use
test.each(Jest) or@pytest.mark.parametrizefor table-driven tests with multiple input/output pairs - Snapshot tests for complex output structures, but review snapshots on every change
--coverage --collectCoverageFromto see which lines are untested- Use
fakerorfactory-boyto generate realistic test data instead of hand-crafting fixtures - Jest's
jest.useFakeTimers()/ Python'sfreezegunto control time-dependent tests
Related Skills
- debugger
- code-reviewer
- api-designer
- refactorer
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

