Use when writing tests, debugging failures, or investigating bugs - provides TDD guidance, test generation patterns, systematic debugging framework. Activates when user says "write tests", "this test fails", "debug this", mentions "TDD", "test coverage", or encounters errors/bugs.
Provides systematic TDD guidance and test generation patterns for all scenarios. Activates when you say "write tests", "debug this", mention TDD, or encounter errors/bugs.
/plugin marketplace add xbklairith/kisune/plugin install dev-workflow@kisuneThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Guide test-driven development (TDD), generate comprehensive test suites, and provide systematic debugging frameworks. Ensures code is well-tested and bugs are resolved methodically rather than through trial-and-error.
Activate this skill when:
For complete TDD workflow, use Skill tool to invoke: dev-workflow:test-driven-development
How to activate:
Use Skill tool: Skill(skill: "dev-workflow:test-driven-development")
The test-driven-development skill provides:
Quick TDD Summary:
This skill focuses on test generation strategies and systematic debugging. For TDD methodology details, use the dedicated skill.
Goal: Generate comprehensive test suites covering all scenarios
Test expected, typical usage:
describe('calculatePositionSize', () => {
it('should calculate correct position size for valid inputs', () => {
const result = calculatePositionSize(
10000, // account balance
0.02, // 2% risk
150.50, // entry price
148.00 // stop loss
);
expect(result).toBe(80); // $200 risk / $2.50 per share
});
it('should handle large account balances', () => {
const result = calculatePositionSize(
1000000, // $1M account
0.01, // 1% risk
100,
99
);
expect(result).toBe(10000);
});
});
Test limits and boundaries:
describe('calculatePositionSize - edge cases', () => {
it('should handle very small risk percentage', () => {
const result = calculatePositionSize(
10000,
0.001, // 0.1% risk
100,
99
);
expect(result).toBe(10); // $10 risk / $1 per share
});
it('should handle entry price equal to stop loss', () => {
expect(() => {
calculatePositionSize(10000, 0.02, 100, 100);
}).toThrow('Entry price cannot equal stop loss');
});
it('should handle very small price differences', () => {
const result = calculatePositionSize(
10000,
0.02,
100.10,
100.00
);
expect(result).toBe(2000); // $200 / $0.10
});
it('should round down fractional shares', () => {
const result = calculatePositionSize(
10000,
0.02,
150.75, // Creates fractional result
148.00
);
// Should be whole number, not fractional
expect(Number.isInteger(result)).toBe(true);
});
});
Test error handling:
describe('calculatePositionSize - error cases', () => {
it('should reject negative account balance', () => {
expect(() => {
calculatePositionSize(-10000, 0.02, 100, 99);
}).toThrow('Account balance must be positive');
});
it('should reject zero account balance', () => {
expect(() => {
calculatePositionSize(0, 0.02, 100, 99);
}).toThrow('Account balance must be positive');
});
it('should reject risk percentage over 100%', () => {
expect(() => {
calculatePositionSize(10000, 1.5, 100, 99);
}).toThrow('Risk percentage must be between 0 and 1');
});
it('should reject negative risk percentage', () => {
expect(() => {
calculatePositionSize(10000, -0.02, 100, 99);
}).toThrow('Risk percentage must be between 0 and 1');
});
it('should handle null inputs gracefully', () => {
expect(() => {
calculatePositionSize(null, 0.02, 100, 99);
}).toThrow();
});
it('should handle undefined inputs gracefully', () => {
expect(() => {
calculatePositionSize(undefined, 0.02, 100, 99);
}).toThrow();
});
});
Test component interactions:
describe('login flow - integration', () => {
it('should complete full authentication flow', async () => {
// Test entire flow from request to response
const response = await request(app)
.post('/api/auth/login')
.send({
email: 'user@example.com',
password: 'SecureP@ss123'
});
// Verify response
expect(response.status).toBe(200);
expect(response.body.data.accessToken).toBeTruthy();
// Verify token is valid
const decoded = jwt.verify(
response.body.data.accessToken,
process.env.JWT_SECRET
);
expect(decoded.id).toBeTruthy();
// Verify user can access protected route
const protectedResponse = await request(app)
.get('/api/user/profile')
.set('Authorization', `Bearer ${response.body.data.accessToken}`);
expect(protectedResponse.status).toBe(200);
});
it('should prevent access with expired token', async () => {
// Create expired token
const expiredToken = jwt.sign(
{ id: 'user-id' },
process.env.JWT_SECRET,
{ expiresIn: '-1h' } // Already expired
);
// Attempt to access protected route
const response = await request(app)
.get('/api/user/profile')
.set('Authorization', `Bearer ${expiredToken}`);
expect(response.status).toBe(401);
expect(response.body.error.code).toBe('TOKEN_EXPIRED');
});
});
describe('[Component/Function Name]', () => {
// Setup and teardown
beforeEach(() => {
// Reset state, create test data
});
afterEach(() => {
// Clean up, reset mocks
});
// NORMAL CASES
describe('normal operation', () => {
it('should [expected behavior for typical input]', () => {
// Test implementation
});
});
// EDGE CASES
describe('edge cases', () => {
it('should handle [boundary condition]', () => {
// Test implementation
});
});
// ERROR CASES
describe('error handling', () => {
it('should reject [invalid input]', () => {
expect(() => {
// Call with invalid input
}).toThrow('Expected error message');
});
});
// INTEGRATION
describe('integration', () => {
it('should work with [other component]', () => {
// Test interaction
});
});
});
Goal: Resolve bugs methodically, not through random trial-and-error
Four-Phase Framework:
Goal: Understand exactly what's going wrong
Process:
Reproduce Bug Consistently
Steps to reproduce:
1. Navigate to login page
2. Enter email: user@example.com
3. Enter password: TestPass123
4. Click submit
5. Observe: Error message "Network request failed"
Reproducibility: 10/10 attempts failed
Identify Symptoms
Gather Evidence
# Check logs
tail -f logs/app.log
# Check network requests (browser dev tools)
# Check console errors
# Check server logs
Collect:
Form Initial Hypothesis
Hypothesis: API endpoint is returning 500 error instead of 400
Evidence:
- Console shows "Network request failed"
- Server logs show 500 error at time of attempt
- Database logs show constraint violation
Next step: Check what's causing the 500
Goal: Identify when bug occurs and when it doesn't
Questions to Answer:
When Does It Fail?
When Does It Work?
What Changed Recently?
# Check recent commits
git log --since="2 days ago" --oneline
# Check what changed in specific file
git log -p path/to/file.js
# See when bug was introduced
git bisect
Environmental Factors?
Pattern Analysis Example:
Bug Pattern Analysis:
FAILS when:
- Email contains + symbol (e.g., user+test@example.com)
- Password is exactly 8 characters
- User account was created after 2025-01-01
WORKS when:
- Email is standard format (user@example.com)
- Password is 9+ characters
- User account is older
Pattern identified: Email validation regex doesn't handle + symbol
Goal: Test theories systematically until root cause found
Process:
Create Minimal Test Case
// Isolate the bug
it('should accept email with plus symbol', () => {
const email = 'user+test@example.com';
const result = validateEmail(email);
expect(result).toBe(true); // Currently fails
});
Add Instrumentation
function validateEmail(email) {
console.log('Input email:', email);
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const isValid = regex.test(email);
console.log('Regex test result:', isValid);
console.log('Regex used:', regex);
return isValid;
}
Test Hypothesis
// Hypothesis: Regex doesn't handle + symbol
// Test with minimal input
validateEmail('user+test@example.com');
// Output:
// Input email: user+test@example.com
// Regex test result: true
//
// Hypothesis REJECTED: Regex accepts + symbol
// Form new hypothesis: Something else is rejecting it
// Check database constraint
// Found: Database column has CHECK constraint excluding +
// Hypothesis CONFIRMED!
Iterate Until Root Cause Found Keep forming and testing hypotheses until you identify exact cause.
Goal: Fix bug permanently with regression protection
Process:
Write Test Reproducing Bug
// This test should FAIL before fix
it('should accept email with plus symbol', async () => {
const email = 'user+test@example.com';
const password = 'SecureP@ss123';
const response = await request(app)
.post('/api/auth/register')
.send({ email, password });
expect(response.status).toBe(201);
expect(response.body.user.email).toBe(email);
});
Run test - verify it fails:
npm test
# ✗ should accept email with plus symbol
# Expected: 201, Received: 400
Fix the Bug
-- Remove overly restrictive database constraint
ALTER TABLE users DROP CONSTRAINT email_format_check;
-- Or update to correct constraint
ALTER TABLE users ADD CONSTRAINT email_format_check
CHECK (email ~* '^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}$');
Verify Test Passes
npm test
# ✓ should accept email with plus symbol
Add Regression Tests
// Add more tests for similar edge cases
describe('email validation - special characters', () => {
const validEmails = [
'user+test@example.com',
'user.name@example.com',
'user_name@example.com',
'user-name@example.com',
'user123@example.com'
];
validEmails.forEach(email => {
it(`should accept ${email}`, async () => {
const response = await request(app)
.post('/api/auth/register')
.send({ email, password: 'SecureP@ss123' });
expect(response.status).toBe(201);
});
});
});
Document Root Cause
/*
* Bug Fix: Email validation now accepts RFC-compliant characters
*
* Root Cause:
* Database CHECK constraint was too restrictive, excluding the + symbol
* which is valid in email addresses per RFC 5322.
*
* Fix:
* Updated CHECK constraint to use proper regex pattern matching RFC 5322.
*
* Date: 2025-01-17
* Related Issue: #234
*/
Commit Fix with Context
git add migrations/003_fix_email_constraint.sql
git add tests/auth/register.test.js
git commit -m "fix: Accept + symbol in email addresses
Database CHECK constraint was rejecting valid emails containing
the + symbol. Updated constraint to match RFC 5322 standard.
Closes #234"
Goal: Identify untested code
Check Coverage:
# Generate coverage report
npm run test:coverage
# Typical output:
# File | % Stmts | % Branch | % Funcs | % Lines |
# ---------------|---------|----------|---------|---------|
# src/auth.js | 87.5 | 75.0 | 100.0 | 87.5 |
# src/orders.js | 45.2 | 33.3 | 60.0 | 45.2 |
Identify Gaps:
Prioritize:
If superpowers:test-driven-development available:
If superpowers:systematic-debugging available:
❌ Writing tests after implementation ❌ Changing tests to match implementation ❌ Testing implementation details instead of behavior ❌ Skipping refactor phase ❌ Testing code that's already tested (overwriting working tests) ❌ Making multiple changes before testing ❌ Debugging by randomly changing code ❌ Committing "console.log" debugging code
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.