Agent skill
test-writing
Skill for the Test Writer agent to create tests before implementation (TDD). Use when executing /sp.test to write tests for a feature or task. Provides test patterns, fixture templates, assertion strategies, and framework-specific guidance for pytest (backend) and vitest/jest (frontend).
Stars
163
Forks
31
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/test-writing
SKILL.md
Test Writing
Skill for creating comprehensive tests following Test-Driven Development (TDD) methodology.
Overview
This skill enables the Test Writer agent to:
- Create tests BEFORE implementation (TDD Red phase)
- Generate appropriate test patterns based on component type
- Design effective fixtures and mocks
- Ensure acceptance criteria coverage
TDD Workflow
/sp.test invoked
|
v
Read spec + contracts
|
v
Identify testable requirements
|
v
Select test patterns
|
v
Write failing tests
|
v
Verify tests fail (RED)
|
v
Report to PM
Test Pattern Selection
Choose patterns based on what you're testing:
| Testing | Pattern | Framework |
|---|---|---|
| Pure functions | Unit tests | pytest / vitest |
| API endpoints | Integration tests | pytest + httpx |
| Database operations | Integration tests | pytest + fixtures |
| React components | Component tests | vitest + testing-library |
| User flows | E2E tests | playwright |
Test Structure
Backend (pytest)
python
"""
Tests for [FEATURE]: [COMPONENT]
Spec: specs/{feature}/spec.md
Task: [TASK_ID]
"""
import pytest
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from app import App
class Test[ComponentName]:
"""Tests for [component] functionality."""
@pytest.fixture
def setup(self):
"""Test setup."""
# Arrange common data
return {"data": "value"}
def test_should_[behavior]_when_[condition](self, setup):
"""[AC: acceptance criteria reference]"""
# Arrange
input_data = setup["data"]
# Act
result = function_under_test(input_data)
# Assert
assert result == expected_value
def test_should_raise_error_when_invalid_input(self):
"""Test error handling."""
# Arrange
invalid_input = None
# Act & Assert
with pytest.raises(ValueError, match="expected error"):
function_under_test(invalid_input)
Frontend (vitest)
typescript
/**
* Tests for [FEATURE]: [COMPONENT]
* Spec: specs/{feature}/spec.md
* Task: [TASK_ID]
*/
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
describe('[ComponentName]', () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe('when [scenario]', () => {
it('should [expected behavior]', () => {
// Arrange
render(<Component prop="value" />);
// Act
fireEvent.click(screen.getByRole('button'));
// Assert
expect(screen.getByText('result')).toBeInTheDocument();
});
});
describe('error handling', () => {
it('should display error when [condition]', () => {
// Arrange & Act
render(<Component invalidProp={null} />);
// Assert
expect(screen.getByRole('alert')).toBeInTheDocument();
});
});
});
Fixture Patterns
Factory Pattern
python
# tests/fixtures/factories.py
from dataclasses import dataclass
from typing import Optional
@dataclass
class UserFactory:
"""Factory for creating test users."""
id: int = 1
name: str = "Test User"
email: str = "test@example.com"
@classmethod
def create(cls, **overrides):
defaults = {"id": 1, "name": "Test User", "email": "test@example.com"}
defaults.update(overrides)
return cls(**defaults)
Database Fixtures
python
# tests/fixtures/database.py
import pytest
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
@pytest.fixture
def db_session():
"""Provide a clean database session for each test."""
engine = create_engine("sqlite:///:memory:")
Session = sessionmaker(bind=engine)
session = Session()
yield session
session.rollback()
session.close()
Mock Strategies
External API Mock
python
from unittest.mock import patch, MagicMock
@patch('module.external_api_client')
def test_api_integration(mock_client):
mock_client.get.return_value = {"status": "success"}
result = function_that_calls_api()
assert result["status"] == "success"
React Hook Mock
typescript
vi.mock('./useApi', () => ({
useApi: vi.fn(() => ({
data: { items: [] },
loading: false,
error: null,
})),
}));
Edge Case Checklist
Always test these scenarios:
- Empty input (null, undefined, empty string, empty array)
- Maximum values (string length, array size, numeric bounds)
- Minimum values (zero, negative numbers)
- Invalid formats (wrong type, malformed data)
- Unauthorized access attempts
- Network/database failure scenarios
- Concurrent operation handling
- Boundary conditions
Acceptance Criteria Mapping
Map each test to acceptance criteria from spec:
python
class TestUserRegistration:
"""
User Story: As a new user, I want to register an account
Spec: specs/auth/spec.md#US1
"""
def test_should_create_user_when_valid_data(self):
"""AC1: User can register with email and password."""
pass
def test_should_send_verification_email(self):
"""AC2: Verification email is sent after registration."""
pass
def test_should_reject_duplicate_email(self):
"""AC3: Duplicate emails are rejected with clear error."""
pass
References
For detailed guidance, see:
references/test-patterns.md- Common testing patterns and examplesreferences/fixture-guide.md- Fixture creation best practices
Quality Checklist
Before completing tests:
- All acceptance criteria have tests
- Edge cases covered
- Error scenarios tested
- Tests follow naming convention
- Fixtures are reusable
- Mocks are isolated
- Tests are independent (no order dependency)
- Tests fail correctly (TDD Red phase verified)
Run Commands
bash
# Backend
pytest tests/{feature}/ -v
pytest tests/{feature}/ -v --tb=short # Shorter output
pytest tests/{feature}/test_file.py::TestClass::test_method -v # Single test
# Frontend
npm test -- tests/{feature}/
npm test -- tests/{feature}/ --watch # Watch mode
npm test -- --testNamePattern="should create" # Pattern match
Didn't find tool you were looking for?