🎯 Recommended Samples
Balanced sample collections from various categories for you to explore
Test Pyramid Examples - Testing Strategy Guide
Comprehensive test pyramid implementation examples including unit tests, integration tests, E2E tests, test organization, and strategic testing patterns for balanced software quality assurance
📝 Test Pyramid Foundation and Principles markdown
🟢 simple
⭐⭐
Complete test pyramid implementation with balanced testing levels, proper organization, and strategic test placement guidelines
⏱️ 60 min
🏷️ test pyramid, strategy, foundation, principles
Prerequisites:
Testing fundamentals, JavaScript/TypeScript, Test frameworks
# Test Pyramid Foundation and Principles
## Overview
The Test Pyramid is a testing strategy that emphasizes a balanced approach to software testing with the majority of tests being fast, isolated unit tests at the base, fewer integration tests in the middle, and even fewer end-to-end tests at the top.
## Test Pyramid Structure
### Level 1: Unit Tests (70%)
- **Purpose**: Test individual components in isolation
- **Characteristics**: Fast, cheap, numerous, reliable
- **Examples**: Function validation, class behavior, component logic
- **Tools**: Jest, Mocha, JUnit, Pytest
### Level 2: Integration Tests (20%)
- **Purpose**: Test how components work together
- **Characteristics**: Medium speed, moderate cost, fewer than unit tests
- **Examples**: Database interactions, API integrations, service communication
- **Tools**: TestContainers, Supertest, Spring Boot Test
### Level 3: End-to-End Tests (10%)
- **Purpose**: Test complete user workflows
- **Characteristics**: Slow, expensive, few, comprehensive
- **Examples**: User journeys, critical paths, cross-system workflows
- **Tools**: Playwright, Cypress, Selenium
## Implementation Strategy
### 1. Project Structure
```
project/
├── src/
│ ├── components/ # UI components
│ ├── services/ # Business logic
│ ├── utils/ # Utilities
│ └── api/ # API layer
├── tests/
│ ├── unit/ # Unit tests
│ │ ├── components/
│ │ ├── services/
│ │ └── utils/
│ ├── integration/ # Integration tests
│ │ ├── api/
│ │ ├── database/
│ │ └── services/
│ ├── e2e/ # End-to-end tests
│ │ ├── user-journeys/
│ │ └── critical-paths/
│ └── fixtures/ # Test data and utilities
└── test-configs/ # Test configuration files
```
## Best Practices
### 1. Test Organization
- Group related tests in describe blocks
- Use clear, descriptive test names
- Follow AAA pattern (Arrange, Act, Assert)
- Keep tests independent and isolated
### 2. Test Data
- Use factories or fixtures for test data
- Avoid hardcoded test data
- Clean up test data after each test
- Use realistic but simple data
### 3. Test Maintenance
- Regular review and refactoring
- Remove redundant tests
- Update tests when requirements change
- Monitor test execution time
### 4. Coverage Targets
- Unit tests: 80-90% coverage
- Integration tests: Critical paths coverage
- E2E tests: Core user journeys coverage
This foundation provides a solid base for implementing a comprehensive test pyramid strategy that ensures quality while maintaining development velocity.
💻 Test Pyramid Implementation Patterns javascript
🔴 complex
⭐⭐⭐⭐
Advanced implementation patterns including test automation, CI/CD integration, test data management, and enterprise-level testing strategies
⏱️ 90 min
🏷️ test pyramid, implementation, automation, enterprise
Prerequisites:
Advanced testing, CI/CD, JavaScript/TypeScript, DevOps
// Test Pyramid Implementation Patterns
// 1. test-setup/base-test-setup.js - Shared Test Infrastructure
const { beforeAll, afterAll, beforeEach, afterEach } = require('@jest/globals');
const { setupDatabase, cleanupDatabase } = require('./database-setup');
const { startTestServer, stopTestServer } = require('./test-server');
const TestLogger = require('./test-logger');
class BaseTestSetup {
constructor(options = {}) {
this.options = {
useDatabase: options.useDatabase !== false,
useTestServer: options.useTestServer !== false,
logLevel: options.logLevel || 'info',
timeout: options.timeout || 10000,
...options
};
this.testLogger = new TestLogger(this.options.logLevel);
}
async setupGlobal() {
if (this.options.useDatabase) {
await setupDatabase();
this.testLogger.info('Database setup complete');
}
if (this.options.useTestServer) {
this.server = await startTestServer();
this.testLogger.info('Test server started');
}
}
async cleanupGlobal() {
if (this.server) {
await stopTestServer(this.server);
this.testLogger.info('Test server stopped');
}
if (this.options.useDatabase) {
await cleanupDatabase();
this.testLogger.info('Database cleanup complete');
}
}
async setupEach() {
if (this.options.useDatabase) {
await this.resetDatabase();
}
this.testContext = {
startTime: Date.now(),
testId: Math.random().toString(36).substr(2, 9),
logger: this.testLogger
};
}
async cleanupEach(testResult) {
if (this.testContext) {
const duration = Date.now() - this.testContext.startTime;
this.testLogger.info(`Test completed in ${duration}ms`, {
testId: this.testContext.testId,
result: testResult
});
}
}
async resetDatabase() {
// Reset database to clean state
await cleanupDatabase();
await setupDatabase();
}
getTestContext() {
return this.testContext;
}
}
// 2. test-helpers/api-test-helper.js - API Testing Utilities
class ApiTestHelper {
constructor(baseUrl = 'http://localhost:3000') {
this.baseUrl = baseUrl;
this.defaultHeaders = {
'Content-Type': 'application/json',
'Accept': 'application/json'
};
}
async request(method, endpoint, data = null, options = {}) {
const url = `${this.baseUrl}${endpoint}`;
const config = {
method,
headers: { ...this.defaultHeaders, ...options.headers },
...options
};
if (data && method !== 'GET') {
config.body = JSON.stringify(data);
}
const response = await fetch(url, config);
return {
status: response.status,
headers: response.headers,
data: await response.json(),
ok: response.ok
};
}
// Assertion helpers
assertSuccess(response, expectedStatus = 200) {
if (response.status !== expectedStatus) {
throw new Error(`Expected status ${expectedStatus}, got ${response.status}`);
}
}
assertContains(response, expectedData) {
expect(response.data).toMatchObject(expectedData);
}
}
// 3. test-helpers/database-test-helper.js - Database Testing Utilities
class DatabaseTestHelper {
constructor(connection) {
this.connection = connection;
this.fixtures = {};
}
async loadFixtures(fixtureName, data) {
await this.connection.query(
`INSERT INTO ${fixtureName} (${Object.keys(data[0]).join(', ')}) VALUES ?`,
[data.map(item => Object.values(item))]
);
this.fixtures[fixtureName] = data;
}
async clearTable(tableName) {
await this.connection.query(`DELETE FROM ${tableName}`);
delete this.fixtures[tableName];
}
async resetDatabase() {
const tables = Object.keys(this.fixtures);
for (const table of tables) {
await this.clearTable(table);
}
}
async countRecords(tableName) {
const [result] = await this.connection.query(`SELECT COUNT(*) as count FROM ${tableName}`);
return result[0].count;
}
async findRecord(tableName, criteria) {
const whereClause = Object.keys(criteria)
.map(key => `${key} = ?`)
.join(' AND ');
const values = Object.values(criteria);
const [result] = await this.connection.query(
`SELECT * FROM ${tableName} WHERE ${whereClause}`,
values
);
return result[0] || null;
}
}
module.exports = {
BaseTestSetup,
ApiTestHelper,
DatabaseTestHelper
};