skills/test-driven-development/SKILL.md
Enforce Test-Driven Development (TDD) workflow for all code changes. Apply PROACTIVELY by default using Red-Green-Refactor cycles for features, bug fixes, and refactoring.
npx skillsauth add straub/agent-skills test-driven-developmentInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Use this skill PROACTIVELY - Apply TDD to all code changes by default. Tests come first, implementation follows.
TDD is about design, confidence, and rapid feedback. Write tests first to guide better interfaces and simpler implementations. The goal: "Clean code that works" — Ron Jeffries
This is your core workflow - use it for every code change:
Write ONE test that describes the behavior you want:
describe('calculateDiscount', () => {
it('applies 10% discount when total exceeds $100', () => {
const total = calculateDiscount(150)
expect(total).toBe(135)
})
})
Run the test - It MUST fail. This proves you're testing something real.
Write the minimum code to make the test pass:
function calculateDiscount(amount: number): number {
if (amount > 100) {
return amount * 0.9
}
return amount
}
Run the test - It should now pass. Don't add extra features or perfect the code yet.
Improve the code while keeping all tests green:
Run tests after each change - They must stay green.
Pick the next test and start over. Small steps, frequent validation.
Apply TDD proactively to:
✅ New features - Start with a test describing desired behavior
✅ Bug fixes - Write a failing test that reproduces the bug, then fix it
✅ Refactoring - Tests ensure behavior doesn't change
✅ API endpoints - Test request/response contracts
✅ Business logic - Test calculations, validations, transformations
✅ Any code change - Default to TDD unless truly impossible
Skip only for:
Test individual functions in isolation:
describe('validateEmail', () => {
it('returns true for valid email', () => {
expect(validateEmail('[email protected]')).toBe(true)
})
it('returns false for missing @', () => {
expect(validateEmail('userexample.com')).toBe(false)
})
it('handles null gracefully', () => {
expect(validateEmail(null)).toBe(false)
})
})
Test components working together:
describe('POST /api/users', () => {
it('creates user and returns 201', async () => {
const response = await request(app)
.post('/api/users')
.send({ email: '[email protected]' })
expect(response.status).toBe(201)
expect(response.body.email).toBe('[email protected]')
})
it('returns 400 for invalid email', async () => {
const response = await request(app)
.post('/api/users')
.send({ email: 'invalid' })
expect(response.status).toBe(400)
})
})
Always test these scenarios:
Mock at system boundaries to keep tests fast and reliable:
jest.mock('@/lib/api-client', () => ({
fetchUser: jest.fn(() => Promise.resolve({
id: 1,
email: '[email protected]'
}))
}))
jest.mock('@/lib/database', () => ({
query: jest.fn(() => Promise.resolve([
{ id: 1, name: 'Test User' }
]))
}))
Don't over-mock: Only mock external dependencies (APIs, databases, file system). Let real code run when possible.
❌ Skipping the RED step - Always see the test fail first
❌ Writing too much code - Only write enough to pass the current test
❌ Skipping refactoring - Clean up continuously, don't accumulate debt
❌ Testing implementation - Test behavior/outputs, not internal details
❌ Over-mocking - Mock only external dependencies, not everything
RED → GREEN → REFACTOR → REPEAT
RED: Write test. Watch it FAIL.
GREEN: Write minimum code to PASS.
REFACTOR: Clean up. Keep tests GREEN.
Remember: Tests first, always. No production code without a failing test driving it.
testing
A template for creating new agent skills. Replace this description with a clear explanation of what your skill does and when agents should use it. Include specific keywords that help agents identify relevant tasks.
testing
Use ANY TIME running tests (npm test, node --test, pytest, etc.) to capture output and prevent context overflow.
tools
Interact with Jira using the jira-cli command-line tool to manage issues, sprints, epics, and boards. Use when working with Jira tickets, sprint planning, issue tracking, or when the user mentions Jira, tickets, sprints, epics, or issue management.
tools
Comprehensive workflow for managing GitHub PR review comments using gh CLI and GraphQL API. Use when asked to address review comments, find unreplied comments, reply to review threads, or resolve/unresolve review conversations. Supports finding ALL comments across pagination boundaries, replying to threads, and resolving conversations.