testing-strategies
A reference guide for effective software testing across all levels of the testing pyramid.
Install
mkdir -p .claude/skills/testing-strategies && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/17045" && unzip -o skill.zip -d .claude/skills/testing-strategies && rm skill.zipInstalls to .claude/skills/testing-strategies
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Testing strategies, patterns, and best practices for production codeKey capabilities
- →Apply FIRST principles for unit testing (Fast, Isolated, Repeatable, Self-verifying, Timely)
- →Structure unit tests using the AAA Pattern (Arrange, Act, Assert)
- →Implement table-driven tests for multiple test cases
- →Use mocking for isolating dependencies in unit tests
- →Set up integration tests for databases and HTTP APIs
How it works
The skill provides guidelines and code examples for structuring unit, integration, and end-to-end tests, emphasizing principles like isolation, repeatability, and behavior-driven testing.
Inputs & outputs
When to use testing-strategies
- →Write isolated unit tests
- →Structure integration test suites
- →Implement table-driven tests
- →Adopt testing best practices
About this skill
Testing Strategies Skill
Overview
This skill provides comprehensive guidelines for implementing effective testing strategies across unit, integration, and end-to-end testing.
Testing Pyramid
/\
/ \ E2E Tests (10%)
/____\ Slow, expensive, critical paths
/ \
/________\ Integration Tests (30%)
/ \ Component interactions, APIs
/____________\
/ \
Unit Tests (60%) Fast, cheap, comprehensive
Unit Testing
1. Principles
// FIRST Principles:
// F - Fast (milliseconds)
// I - Isolated (no dependencies)
// R - Repeatable (same result every time)
// S - Self-verifying (no manual checking)
// T - Timely (write with code)
// AAA Pattern:
// Arrange - Set up test data and mocks
// Act - Execute the code under test
// Assert - Verify the results
func TestUserService_CreateUser(t *testing.T) {
// Arrange
mockRepo := &mockUserRepository{}
mockRepo.On("Create", mock.Anything, mock.Anything).Return(nil)
service := NewUserService(mockRepo)
ctx := context.Background()
req := CreateUserRequest{
Email: "[email protected]",
Name: "John Doe",
}
// Act
user, err := service.CreateUser(ctx, req)
// Assert
assert.NoError(t, err)
assert.NotNil(t, user)
assert.Equal(t, "[email protected]", user.Email)
mockRepo.AssertExpectations(t)
}
2. Table-Driven Tests
func TestCalculateDiscount(t *testing.T) {
tests := []struct {
name string
price float64
discountCode string
expectedPrice float64
expectedError bool
}{
{
name: "valid 10% discount",
price: 100.0,
discountCode: "SAVE10",
expectedPrice: 90.0,
expectedError: false,
},
{
name: "valid 20% discount",
price: 100.0,
discountCode: "SAVE20",
expectedPrice: 80.0,
expectedError: false,
},
{
name: "invalid discount code",
price: 100.0,
discountCode: "INVALID",
expectedPrice: 0.0,
expectedError: true,
},
{
name: "negative price",
price: -50.0,
discountCode: "SAVE10",
expectedPrice: 0.0,
expectedError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := CalculateDiscount(tt.price, tt.discountCode)
if tt.expectedError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.InDelta(t, tt.expectedPrice, result, 0.01)
}
})
}
}
3. Mocking
// Interface for dependency injection
type EmailService interface {
Send(ctx context.Context, to string, subject string, body string) error
}
// Mock implementation
type mockEmailService struct {
mock.Mock
}
func (m *mockEmailService) Send(ctx context.Context, to string, subject string, body string) error {
args := m.Called(ctx, to, subject, body)
return args.Error(0)
}
// Test with mock
func TestNotificationService_NotifyUser(t *testing.T) {
mockEmail := &mockEmailService{}
mockEmail.On("Send",
mock.Anything,
"[email protected]",
"Welcome!",
mock.Anything,
).Return(nil)
service := NewNotificationService(mockEmail)
err := service.NotifyUser(context.Background(), "[email protected]", "Welcome!")
assert.NoError(t, err)
mockEmail.AssertCalled(t, "Send",
mock.Anything,
"[email protected]",
"Welcome!",
mock.Anything,
)
}
Integration Testing
1. Database Integration
func TestUserRepository_Create(t *testing.T) {
// Setup test database
ctx := context.Background()
db := setupTestDB(t)
defer teardownTestDB(t, db)
repo := NewUserRepository(db)
// Test
user := &User{
Email: "[email protected]",
Name: "Test User",
}
err := repo.Create(ctx, user)
require.NoError(t, err)
assert.NotEmpty(t, user.ID)
// Verify in database
var count int
err = db.QueryRowContext(ctx, "SELECT COUNT(*) FROM users WHERE email = $1", user.Email).Scan(&count)
require.NoError(t, err)
assert.Equal(t, 1, count)
}
// Test database setup
type testDB struct {
*sql.DB
name string
}
func setupTestDB(t *testing.T) *testDB {
// Create isolated test database
dbName := fmt.Sprintf("test_%s_%d", t.Name(), time.Now().Unix())
connStr := fmt.Sprintf("host=localhost user=postgres password=secret dbname=%s sslmode=disable", dbName)
db, err := sql.Open("postgres", connStr)
require.NoError(t, err)
// Run migrations
runMigrations(db)
return &testDB{DB: db, name: dbName}
}
func teardownTestDB(t *testing.T, db *testDB) {
db.Close()
// Drop test database
}
2. HTTP API Testing
// API integration test
import request from 'supertest';
import { app } from '../src/app';
import { setupTestDB, teardownTestDB } from './helpers/database';
describe('POST /api/users', () => {
beforeAll(async () => {
await setupTestDB();
});
afterAll(async () => {
await teardownTestDB();
});
it('should create a new user', async () => {
const response = await request(app)
.post('/api/users')
.send({
email: '[email protected]',
name: 'Test User'
})
.expect(201);
expect(response.body).toMatchObject({
email: '[email protected]',
name: 'Test User'
});
expect(response.body.id).toBeDefined();
});
it('should return 400 for invalid email', async () => {
const response = await request(app)
.post('/api/users')
.send({
email: 'invalid-email',
name: 'Test User'
})
.expect(400);
expect(response.body.error).toBeDefined();
});
it('should return 409 for duplicate email', async () => {
// Create user first
await request(app)
.post('/api/users')
.send({
email: '[email protected]',
name: 'Test User'
});
// Try to create again
await request(app)
.post('/api/users')
.send({
email: '[email protected]',
name: 'Test User'
})
.expect(409);
});
});
3. External Service Testing
// Use test containers for external services
func TestWithRedis(t *testing.T) {
ctx := context.Background()
// Start Redis container
req := testcontainers.ContainerRequest{
Image: "redis:latest",
ExposedPorts: []string{"6379/tcp"},
WaitingFor: wait.ForListeningPort("6379/tcp"),
}
redisC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: req,
Started: true,
})
require.NoError(t, err)
defer redisC.Terminate(ctx)
// Connect to Redis
endpoint, err := redisC.Endpoint(ctx, "")
require.NoError(t, err)
client := redis.NewClient(&redis.Options{
Addr: endpoint,
})
// Test cache operations
cache := NewCache(client)
err = cache.Set(ctx, "key", "value", time.Hour)
require.NoError(t, err)
val, err := cache.Get(ctx, "key")
require.NoError(t, err)
assert.Equal(t, "value", val)
}
End-to-End Testing
1. E2E with Playwright
// e2e/user-journey.spec.ts
import { test, expect } from '@playwright/test';
test.describe('User Registration Flow', () => {
test.beforeEach(async ({ page }) => {
// Setup: Clean database, seed data if needed
await page.goto('/register');
});
test('user can register successfully', async ({ page }) => {
// Fill registration form
await page.fill('[name="email"]', '[email protected]');
await page.fill('[name="password"]', 'SecurePass123!');
await page.fill('[name="confirmPassword"]', 'SecurePass123!');
// Submit form
await page.click('button[type="submit"]');
// Verify redirect to dashboard
await expect(page).toHaveURL('/dashboard');
await expect(page.locator('h1')).toContainText('Welcome');
// Verify user is logged in
await expect(page.locator('[data-testid="user-menu"]')).toBeVisible();
});
test('shows error for existing email', async ({ page }) => {
await page.fill('[name="email"]', '[email protected]');
await page.fill('[name="password"]', 'SecurePass123!');
await page.click('button[type="submit"]');
await expect(page.locator('[data-testid="error-message"]'))
.toContainText('Email already exists');
});
test('validates password requirements', async ({ page }) => {
await page.fill('[name="email"]', '[email protected]');
await page.fill('[name="password"]', 'weak');
await page.click('button[type="submit"]');
await expect(page.locator('[data-testid="password-error"]'))
.toContainText('Password must be at least 8 characters');
});
});
2. Critical Path Testing
// Test only critical user journeys
const criticalPaths = [
{
name: 'Checkout Flow',
steps: [
'Add item to cart',
'Proceed to checkout',
'Fill shipping info',
---
*Content truncated.*
When not to use it
- →When testing private methods
- →When sharing state between tests
- →When using sleep() in tests
Limitations
- →The skill does not test private methods
- →The skill does not share state between tests
- →The skill does not use sleep() in tests
How it compares
This skill offers a structured, principle-driven approach to testing, unlike ad-hoc test writing.
Compared to similar skills
testing-strategies side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| testing-strategies (this skill) | 0 | 6mo | Review | Intermediate |
| webapp-testing | 353 | 4mo | Review | Intermediate |
| ui-ux-expert-skill | 91 | 9mo | Review | Advanced |
| skill-creator | 128 | 4mo | Review | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
webapp-testing
anthropics
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
ui-ux-expert-skill
fercracix33
Technical workflow for implementing accessible React user interfaces with shadcn/ui, Tailwind CSS, and TanStack Query. Includes 6-phase process with mandatory Style Guide compliance, Context7 best practices consultation, Chrome DevTools validation, and WCAG 2.1 AA accessibility standards. Use after Test Agent, Implementer, and Supabase agents complete their work.
skill-creator
anthropics
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.
python-testing-patterns
wshobson
Implement comprehensive testing strategies with pytest, fixtures, mocking, and test-driven development. Use when writing Python tests, setting up test suites, or implementing testing best practices.
dependency-upgrade
wshobson
Manage major dependency version upgrades with compatibility analysis, staged rollout, and comprehensive testing. Use when upgrading framework versions, updating major dependencies, or managing breaking changes in libraries.
playwright-mcp
sfc-gh-dflippo
Browser testing, web scraping, and UI validation using Playwright MCP. Use this skill when you need to test Streamlit apps, validate web interfaces, test responsive design, check accessibility, or automate browser interactions through MCP tools.