TE

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.zip

Installs 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 code
68 charsno explicit “when” trigger
Intermediate

Key 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

You give it
Codebase requiring testing, specific functions or modules to be tested
You get back
Unit tests, integration tests, or E2E tests following best practices and patterns

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.

SkillInstallsUpdatedSafetyDifficulty
testing-strategies (this skill)06moReviewIntermediate
webapp-testing3534moReviewIntermediate
ui-ux-expert-skill919moReviewAdvanced
skill-creator1284moReviewAdvanced

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.

353585

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.

91244

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.

128200

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.

77204

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.

26240

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.

33197

Search skills

Search the agent skills registry