Skip to main content

testing-strategies

Unit, integration, E2E testing and TDD practices

Datos de origen

Repositorio
miles990/claude-software-skills
Última actividad en el origen
8 de enero de 2026 a las 05:30
Idioma detectado de SKILL.md
chino
Estrellas
25
Forks
6

Opciones de instalación

De forma predeterminada está seleccionado el prompt que primero revisa el origen. Puedes cambiar a un comando directo o descargar una copia local.

Revisa los archivos de origen

Lee SKILL.md y los archivos complementarios que muestra SkillsMP antes de decidir si quieres instalarlo.

Explorador de archivos
5 archivos

Mostrando SKILL.md

SKILL.md
Instrucciones de origen · Vista previa de solo lectura
name
testing-strategies
description
Unit, integration, E2E testing and TDD practices
domain
software-engineering
version
1.0.0
tags
["testing","unit-test","integration-test","e2e","tdd","mocking"]
triggers
{"keywords":{"primary":["test","testing","unit test","integration test","e2e","tdd","jest","pytest"],"secondary":["mock","stub","fixture","coverage","assertion","cypress","playwright"]},"context_boost":["quality","ci","automation","reliability"],"context_penalty":["design","architecture","frontend"],"priority":"high"}
collaboration
{"prerequisites":[],"delegation_triggers":[{"trigger":"Backend service to be tested","delegate_to":"backend","context":"Service architecture, dependencies"},{"trigger":"Frontend component to be tested","delegate_to":"frontend","context":"Component props, user interactions"},{"trigger":"API contract tests","delegate_to":"api-design","context":"API specifications, expected behaviors"},{"trigger":"Database fixtures and test data","delegate_to":"database","context":"Schema structure, seed data patterns"}],"receives_context_from":[{"skill":"backend","receives":"[Truncated]"},{"skill":"frontend","receives":"[Truncated]"},{"skill":"api-design","receives":"[Truncated]"},{"skill":"database","receives":"[Truncated]"}],"provides_context_to":[{"skill":"backend","provides":"[Truncated]"},{"skill":"frontend","provides":"[Truncated]"}]}
# Testing Strategies ## Overview Testing pyramid, patterns, and practices for building reliable software. --- ## Testing Pyramid ``` /\ / \ / E2E\ Few, slow, expensive /──────\ / \ /Integration\ Some, medium speed /──────────────\ / \ / Unit Tests \ Many, fast, cheap /____________________\ ``` | Level | Speed | Scope | Quantity | |-------|-------|-------|----------| | Unit | Fast (ms) | Single function/class | Many (70%) | | Integration | Medium (s) | Multiple components | Some (20%) | | E2E | Slow (min) | Full system | Few (10%) | --- ## Unit Testing ### Structure: Arrange-Act-Assert ```typescript describe('calculateDiscount', () => { it('applies 10% discount for orders over $100', () => { // Arrange const order = { items: [{ price: 150 }] }; const discountService = new DiscountService(); // Act const result = discountService.calculateDiscount(order); // Assert expect(result).toBe(15); }); it('returns 0 for orders under $100', () => { // Arrange const order = { items: [{ price: 50 }] }; const discountService = new DiscountService(); // Act const result = discountService.calculateDiscount(order); // Assert expect(result).toBe(0); }); }); ``` ### Mocking ```typescript // Mock dependencies const mockEmailService = { send: jest.fn().mockResolvedValue({ success: true }) }; const mockUserRepo = { findById: jest.fn().mockResolvedValue({ id: '1', email: 'test@example.com' }) }; describe('NotificationService', () => { let service: NotificationService; beforeEach(() => { jest.clearAllMocks(); service = new NotificationService(mockEmailService, mockUserRepo); }); it('sends email to user', async () => { await service.notifyUser('1', 'Hello!'); expect(mockUserRepo.findById).toHaveBeenCalledWith('1'); expect(mockEmailService.send).toHaveBeenCalledWith( 'test@example.com', 'Hello!' ); }); it('throws when user not found', async () => { mockUserRepo.findById.mockResolvedValue(null); await expect(service.notifyUser('999', 'Hello!')) .rejects.toThrow('User not found'); }); }); ``` ### Testing Edge Cases ```typescript describe('parseAge', () => { // Happy path it('parses valid age string', () => { expect(parseAge('25')).toBe(25); }); // Edge cases it('handles zero', () => { expect(parseAge('0')).toBe(0); }); it('handles boundary values', () => { expect(parseAge('1')).toBe(1); expect(parseAge('150')).toBe(150); }); // Error cases it('throws on negative numbers', () => { expect(() => parseAge('-5')).toThrow('Age cannot be negative'); }); it('throws on non-numeric input', () => { expect(() => parseAge('abc')).toThrow('Invalid age format'); }); it('throws on empty string', () => { expect(() => parseAge('')).toThrow('Age is required'); }); // Null/undefined it('throws on null', () => { expect(() => parseAge(null as any)).toThrow(); }); }); ``` --- ## Integration Testing ### API Testing ```typescript import request from 'supertest'; import { app } from '../app'; import { db } from '../database'; describe('POST /api/users', () => { beforeEach(async () => { await db.users.deleteMany({}); }); afterAll(async () => { await db.disconnect(); }); it('creates a new user', async () => { const response = await request(app) .post('/api/users') .send({ email: 'test@example.com', name: 'Test User' }) .expect(201); expect(response.body).toMatchObject({ id: expect.any(String), email: 'test@example.com', name: 'Test User' }); // Verify in database const user = await db.users.findOne({ email: 'test@example.com' }); expect(user).not.toBeNull(); }); it('returns 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).toBe('Invalid email format'); }); it('returns 409 for duplicate email', async () => { // Create first user await request(app) .post('/api/users') .send({ email: 'test@example.com', name: 'First' }); // Try to create duplicate const response = await request(app) .post('/api/users') .send({ email: 'test@example.com', name: 'Second' }) .expect(409); expect(response.body.error).toBe('Email already exists'); }); }); ``` ### Database Testing with Testcontainers ```typescript import { PostgreSqlContainer } from '@testcontainers/postgresql'; import { Pool } from 'pg'; describe('UserRepository', () => { let container: StartedPostgreSqlContainer; let pool: Pool; let repo: UserRepository; beforeAll(async () => { container = await new PostgreSqlContainer().start(); pool = new Pool({ connectionString: container.getConnectionUri() }); await runMigrations(pool); repo = new UserRepository(pool); }, 60000); afterAll(async () => { await pool.end(); await container.stop(); }); beforeEach(async () => { await pool.query('TRUNCATE users CASCADE'); }); it('creates and retrieves user', async () => { const created = await repo.create({ email: 'test@example.com', name: 'Test' }); const found = await repo.findById(created.id); expect(found).toEqual(created); }); }); ``` --- ## E2E Testing ### Playwright ```typescript import { test, expect } from '@playwright/test'; test.describe('User Authentication', () => { test('successful login flow', async ({ page }) => { await page.goto('/login'); // Fill form await page.fill('[data-testid="email-input"]', 'user@example.com'); await page.fill('[data-testid="password-input"]', 'password123'); // Submit await page.click('[data-testid="login-button"]'); // Verify redirect to dashboard await expect(page).toHaveURL('/dashboard'); await expect(page.locator('[data-testid="welcome-message"]')) .toContainText('Welcome, user@example.com'); }); test('shows error for invalid credentials', async ({ page }) => { await page.goto('/login'); await page.fill('[data-testid="email-input"]', 'wrong@example.com'); await page.fill('[data-testid="password-input"]', 'wrongpassword'); await page.click('[data-testid="login-button"]'); await expect(page.locator('[data-testid="error-message"]')) .toBeVisible() .toContainText('Invalid credentials'); }); }); test.describe('Shopping Cart', () => { test('add item and checkout', async ({ page }) => { // Setup - login await page.goto('/login'); await page.fill('[data-testid="email-input"]', 'buyer@example.com'); await page.fill('[data-testid="password-input"]', 'password'); await page.click('[data-testid="login-button"]'); // Browse products await page.goto('/products'); await page.click('[data-testid="product-1"] [data-testid="add-to-cart"]'); // Verify cart await expect(page.locator('[data-testid="cart-count"]')).toHaveText('1'); // Checkout await page.click('[data-testid="cart-icon"]'); await page.click('[data-testid="checkout-button"]'); // Fill shipping await page.fill('[data-testid="address"]', '123 Test St'); await page.click('[data-testid="place-order"]'); // Verify success await expect(page).toHaveURL(/\/orders\/\d+/); await expect(page.locator('[data-testid="order-status"]')) .toContainText('Order Confirmed'); }); }); ``` ### Visual Regression Testing ```typescript import { test, expect } from '@playwright/test'; test('homepage visual regression', async ({ page }) => { await page.goto('/'); // Wait for dynamic content await page.waitForSelector('[data-testid="hero-section"]'); // Take screenshot and compare await expect(page).toHaveScreenshot('homepage.png', { maxDiffPixels: 100, threshold: 0.2 }); }); test('responsive design', async ({ page }) => { await page.setViewportSize({ width: 375, height: 667 }); // iPhone SE await page.goto('/'); await expect(page).toHaveScreenshot('homepage-mobile.png'); }); ``` --- ## Test-Driven Development (TDD) ### Red-Green-Refactor Cycle
Ver en GitHub
Este SKILL.md es muy grande, por eso SkillsMP muestra aqui solo la primera seccion. Ver en GitHub