Testing Skill
Provides test strategy patterns, coverage optimization techniques, and quality assurance procedures for ensuring code quality.
What It Provides
Testing Pyramid- Test distribution ratios (70/20/10 rule)
- Unit, integration, and E2E test strategies
- Test scope and isolation patterns
- AAA pattern (Arrange-Act-Assert)
- Test organization conventions
- Naming and clarity standards
- Minimum coverage thresholds
- Critical path coverage standards
- Coverage analysis procedures
- When to mock vs test real interactions
- Test data management patterns
- Fixture creation approaches
Used By
Tester Agent:- Planning test strategy
- Writing comprehensive tests
- Achieving coverage thresholds
- Following testing best practices
- Validates tests are passing
- Checks coverage meets 80% threshold
- Verifies no skipped tests without justification
- Ensures tests pass before marking features complete
- Validates coverage requirements
- Checks test quality standards
Tools Available
- Read (test files, coverage reports)
- Write (new tests)
- Edit (update existing tests)
- Glob (find test files)
- Grep (search for test patterns)
- Bash (run tests, generate coverage)
Testing Pyramid
Distribute tests following the 70/20/10 rule:
- 70% Unit Tests - Fast, isolated, test individual functions/methods
- 20% Integration Tests - Test component interactions, APIs, database operations
- 10% E2E Tests - Test complete user workflows end-to-end
Test Structure: AAA Pattern
Arrange - Act - Asserttest('should create user with valid data', () => {
// ARRANGE: Set up test data and dependencies
const userData = { email: 'test@example.com', password: 'secure123' };
const mockRepository = createMockRepository();
const service = new UserService(mockRepository);
// ACT: Execute the function under test
const result = service.createUser(userData);
// ASSERT: Verify expected outcomes
expect(result.email).toBe(userData.email);
expect(mockRepository.save).toHaveBeenCalled();
});Coverage Requirements
Minimum Thresholds:- Overall coverage: 80%
- Statements: 80%
- Branches: 75%
- Functions: 80%
- Lines: 80%
- Authentication and authorization
- Payment processing
- Security functions
- Data encryption/decryption
- Financial calculations
- Access control logic
What to Test
High Priority (Must Cover)
- Business logic and algorithms
- Authentication and authorization flows
- Data validation and sanitization
- API endpoints and request handlers
- Database operations and queries
- Error handling and edge cases
- Security-sensitive operations
Medium Priority (Should Cover)
- Utility functions and helpers
- State management logic
- Form validation
- UI component behavior
- Caching logic
- External service integrations
Low Priority (Nice to Cover)
- Simple getters/setters
- Configuration loaders
- Logging statements
- Trivial formatting functions
Mocking Strategy
When to Mock
- External API calls (third-party services)
- Database connections (for unit tests)
- File system operations
- Email/SMS services
- Payment gateways
- Time-dependent code (dates, timers)
- Random number generation
When NOT to Mock
- The code under test
- Pure functions without side effects
- Simple data transformations
- Integration tests (test real interactions)
- Domain models
Test Data Management
Use Fixtures for Consistent Test Data:fixtures/
├── users.js # Standard user test data
├── products.js # Product test data
└── orders.js # Order test datafunction createUserFixture(overrides = {}) {
return {
id: generateId(),
email: 'test@example.com',
name: 'Test User',
role: 'user',
...overrides
};
}Test Organization
project/
├── src/
│ ├── services/
│ │ ├── userService.js
│ │ └── userService.test.js # Co-located with source
│ └── utils/
│ ├── validators.js
│ └── validators.test.js
├── tests/
│ ├── integration/ # Integration tests
│ │ ├── api/
│ │ └── database/
│ ├── e2e/ # End-to-end tests
│ ├── fixtures/ # Shared test data
│ └── setup.js # Global test setup
└── test.config.jsCommon Test Frameworks by Language
JavaScript/TypeScript:- Jest, Vitest, Mocha, Jasmine
- E2E: Playwright, Cypress, Puppeteer
- pytest, unittest, nose
- E2E: Selenium, Playwright
- testing package, testify
- E2E: chromedp, Selenium
- JUnit 5, TestNG
- E2E: Selenium, Playwright
- Built-in test framework
- E2E: headless_chrome
- RSpec, Minitest
- E2E: Capybara
Consult your test framework's documentation for specific commands.
Coverage Analysis
Identify Coverage Gaps:- Run coverage report
- Find uncovered lines/branches
- Assess criticality of uncovered code
- Write tests for critical uncovered code
- Accept lower coverage for non-critical paths
- 80% coverage with good tests > 100% coverage with bad tests
- Focus on testing critical paths thoroughly
- Some code is too trivial to test
Examples
Unit Test Example
// Test: User validation
test('validates email format', () => {
// Arrange
const validator = new EmailValidator();
const validEmail = 'user@example.com';
const invalidEmail = 'not-an-email';
// Act
const validResult = validator.validate(validEmail);
const invalidResult = validator.validate(invalidEmail);
// Assert
expect(validResult.isValid).toBe(true);
expect(invalidResult.isValid).toBe(false);
});Integration Test Example
// Test: API endpoint with database
test('POST /users creates user in database', async () => {
// Arrange
const userData = { email: 'test@example.com', name: 'Test User' };
// Act
const response = await request(app)
.post('/users')
.send(userData);
// Assert
expect(response.status).toBe(201);
const user = await db.users.findOne({ email: userData.email });
expect(user).toBeDefined();
expect(user.name).toBe(userData.name);
});E2E Test Example
// Test: Complete user workflow
test('user can sign up and log in', async ({ page }) => {
// Arrange
await page.goto('/signup');
// Act: Sign up
await page.fill('[name="email"]', 'test@example.com');
await page.fill('[name="password"]', 'secure123');
await page.click('button[type="submit"]');
// Assert: Redirected to dashboard
await expect(page).toHaveURL('/dashboard');
await expect(page.locator('h1')).toContainText('Welcome');
// Act: Log out and log back in
await page.click('button:has-text("Logout")');
await page.goto('/login');
await page.fill('[name="email"]', 'test@example.com');
await page.fill('[name="password"]', 'secure123');
await page.click('button[type="submit"]');
// Assert: Back on dashboard
await expect(page).toHaveURL('/dashboard');
});Rules
DO
- Write tests before marking features complete
- Test behavior, not implementation details
- Test error cases and edge cases
- Use descriptive test names
- Keep tests independent (no shared state)
- Mock external dependencies
- Test critical paths with high coverage
- Clean up test data after each test
DON'T
- Skip tests to speed up development
- Test implementation details
- Share mutable state between tests
- Commit commented-out tests
- Leave TODOs in test files
- Test private methods directly
- Write tests that depend on execution order
- Hardcode dates or random values
- Ignore flaky tests (fix or remove them)
- Test framework code or third-party libraries
Implementation Details
Location: .claude/skills/testing/SKILL.md
Model: Sonnet
Tools Used:- Read (test files, coverage reports)
- Write (new tests)
- Edit (update tests)
- Glob (find test files)
- Grep (search patterns)
- Bash (run tests, coverage)
- Test framework config (vitest.config.ts, jest.config.js)
- Test files (*.test.js, *.spec.js)
- Coverage reports (coverage/)
- Fixtures (tests/fixtures/)
See Also
- /agentful-validate - Runs test suite and coverage checks
- Validation Skill - Quality gate definitions including test validation
- Tester Agent - Uses this skill to write comprehensive tests
- Reviewer Agent - Validates test coverage and quality