| name | systematic-testing |
| description | 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. |
Systematic Testing Skill
Purpose
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.
Activation Triggers
Activate this skill when:
- User implements new functionality (auto-suggest tests)
- Tests fail (activate debugging framework)
- User says "write tests for this"
- User mentions "TDD" or "test-driven"
- User asks about debugging or troubleshooting
- User says "this bug..." or "error..."
- Before marking feature complete (verify test coverage)
Core Capabilities
1. Test-Driven Development (TDD)
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:
- Full RED-GREEN-REFACTOR cycle explanation
- Strict TDD enforcement and discipline
- Anti-patterns and rationalizations to avoid
- Detailed examples and verification checklist
Quick TDD Summary:
- RED: Write failing test first
- GREEN: Write minimal code to pass
- REFACTOR: Clean up while tests stay green
This skill focuses on test generation strategies and systematic debugging. For TDD methodology details, use the dedicated skill.
2. Test Generation
Goal: Generate comprehensive test suites covering all scenarios
Test Categories
Normal Cases (Happy Path)
Test expected, typical usage:
describe('calculatePositionSize', () => {
it('should calculate correct position size for valid inputs', () => {
const result = calculatePositionSize(
10000,
0.02,
150.50,
148.00
);
expect(result).toBe(80);
});
it('should handle large account balances', () => {
const result = calculatePositionSize(
1000000,
0.01,
100,
99
);
expect(result).toBe(10000);
});
});
Edge Cases (Boundary Conditions)
Test limits and boundaries:
describe('calculatePositionSize - edge cases', () => {
it('should handle very small risk percentage', () => {
const result = calculatePositionSize(
10000,
0.001,
100,
99
);
expect(result).toBe(10);
});
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);
});
it('should round down fractional shares', () => {
const result = calculatePositionSize(
,
,
,
);
(.(result)).();
});
});
Error Cases (Invalid Inputs)
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, );
}).();
});
(, {
( {
(, , , );
}).();
});
(, {
( {
(, , , );
}).();
});
});
Integration Cases
Test component interactions:
describe('login flow - integration', () => {
it('should complete full authentication flow', async () => {
const response = await request(app)
.post('/api/auth/login')
.send({
email: 'user@example.com',
password: 'SecureP@ss123'
});
expect(response.status).toBe(200);
expect(response.body.data.accessToken).toBeTruthy();
const decoded = jwt.verify(
response.body.data.accessToken,
process.env.JWT_SECRET
);
expect(decoded.id).toBeTruthy();
const protectedResponse = await request(app)
.get('/api/user/profile')
.set('Authorization', `Bearer `);
(protectedResponse.).();
});
(, () => {
expiredToken = jwt.(
{ : },
process..,
{ : }
);
response = (app)
.()
.(, );
(response.).();
(response...).();
});
});
Test Generation Template
describe('[Component/Function Name]', () => {
beforeEach(() => {
});
afterEach(() => {
});
describe('normal operation', () => {
it('should [expected behavior for typical input]', () => {
});
});
describe('edge cases', () => {
it('should handle [boundary condition]', () => {
});
});
describe('error handling', () => {
it('should reject [invalid input]', () => {
expect(() => {
}).toThrow('Expected error message');
});
});
describe('integration', () => {
it('should work with [other component]', () => {
});
});
});
3. Systematic Debugging Framework
Goal: Resolve bugs methodically, not through random trial-and-error
Four-Phase Framework:
Phase 1: Root Cause Investigation
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
- What's the visible error?
- What error messages appear?
- What's the expected vs actual behavior?
-
Gather Evidence
tail -f logs/app.log
Collect:
- Error messages (full text)
- Stack traces
- Log entries
- Network requests/responses
- Input values that trigger bug
-
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
Phase 2: Pattern Analysis
Goal: Identify when bug occurs and when it doesn't
Questions to Answer:
-
When Does It Fail?
- Specific inputs?
- Certain users?
- Particular time of day?
- After specific sequence of actions?
-
When Does It Work?
- Any inputs that succeed?
- Any users unaffected?
- Worked before, broken now?
-
What Changed Recently?
git log --since="2 days ago" --oneline
git log -p path/to/file.js
git bisect
-
Environmental Factors?
- Works locally, fails in production?
- Browser-specific?
- Network conditions?
- Load-related (works with 1 user, fails with 100)?
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
Phase 3: Hypothesis Testing
Goal: Test theories systematically until root cause found
Process:
-
Create Minimal Test Case
it('should accept email with plus symbol', () => {
const email = 'user+test@example.com';
const result = validateEmail(email);
expect(result).toBe(true);
});
-
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
validateEmail('user+test@example.com');
Phase 4: Implementation
Goal: Fix bug permanently with regression protection
Process:
-
Write Test Reproducing Bug
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
-
Fix the Bug
ALTER TABLE users DROP CONSTRAINT email_format_check;
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
Test Coverage Analysis
Goal: Identify untested code
Check Coverage:
npm run test:coverage
Identify Gaps:
- Functions without any tests
- Branches not covered (if statements, error paths)
- Edge cases not tested
- Integration paths missing
Prioritize:
- Critical business logic (highest priority)
- Security-sensitive code
- Complex algorithms
- Error handling paths
- Edge cases
Best Practices
TDD Best Practices
- Always write test first: No exceptions
- One test at a time: Don't write multiple tests before implementing
- Smallest possible step: Each cycle should be quick (5-10 minutes)
- Test behavior, not implementation: Don't test private methods
- Keep tests simple: Tests should be easier to understand than code
Test Quality
- Clear test names: Should read like documentation
- Arrange-Act-Assert: Structure tests consistently
- One assertion per test: Makes failures clear
- No logic in tests: Tests should be simple data
- Independent tests: No test depends on another
Debugging Best Practices
- Reproduce first: Can't fix what you can't reproduce
- Understand before fixing: Don't guess and check
- Fix root cause: Don't just treat symptoms
- Add regression test: Prevent bug from returning
- Document why: Help future debuggers
Integration with Superpowers
If superpowers:test-driven-development available:
- Use for guided TDD workflow
- Enhanced RED-GREEN-REFACTOR cycle
- Additional TDD best practices
If superpowers:systematic-debugging available:
- Use for complex debugging scenarios
- Root cause tracing framework
- Advanced instrumentation guidance
Common Anti-Patterns to Avoid
❌ 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
Notes
- TDD is slower initially but faster overall (fewer bugs, less debugging)
- Good tests are documentation that never gets outdated
- Debugging is detective work, not guessing
- Always add regression tests after fixing bugs
- Test coverage is a minimum bar, not a goal