Menguasai test environment management termasuk environment as code, test containers, dan data seeding untuk testing yang reproducible

Setelah di episode 9 kita mempelajari quality gates in CI/CD, pada episode ini kita mempelajari test environments & test ops — bagaimana mengelola test environments secara efektif. Test environment yang baik memastikan testing reproducible dan reliable.
Mengapa test environments penting? Karena "it works on my machine" adalah masalah klasik. Dengan test environments yang terisolasi dan reproducible, kalian bisa memastikan test results konsisten di semua environment.
Environment as Code:
├── Definition:
│ ├── Environment di-definition sebagai code
│ ├── Version controlled
│ └── Reproducible
├── Tools:
│ ├── Docker Compose
│ ├── Terraform
│ ├── Pulumi
│ └── Kubernetes
└── Benefits:
├── Consistency
├── Reproducibility
├── Scalability
└── Audit trail# docker-compose.test.yml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=test
- DATABASE_URL=postgresql://test:test@db:5432/testdb
depends_on:
- db
- redis
db:
image: postgres:15
environment:
- POSTGRES_USER=test
- POSTGRES_PASSWORD=test
- POSTGRES_DB=testdb
ports:
- "5432:5432"
redis:
image: redis:7
ports:
- "6379:6379"Test Containers:
├── Library untuk menjalankan containers di tests
├── Automatic cleanup
├── Isolated per test
└── Supported: Java, Go, Node.js, Python// test/container.test.ts
import { PostgreSqlContainer } from '@testcontainers/postgresql';
import { PrismaClient } from '@prisma/client';
describe('Database Integration', () => {
let container: PostgreSqlContainer;
let prisma: PrismaClient;
beforeAll(async () => {
container = await new PostgreSqlContainer().start();
prisma = new PrismaClient({
datasources: {
db: {
url: container.getConnectionUri(),
},
},
});
});
afterAll(async () => {
await prisma.$disconnect();
await container.stop();
});
it('should create user', async () => {
const user = await prisma.user.create({
data: { email: 'test@test.com', name: 'Test' },
});
expect(user.id).toBeDefined();
});
});Note
Test containers memberikan isolasi sempurna per test. Setiap test berjalan dengan fresh database yang di-spin up dan di-cleanup secara otomatis. Ini menghilangkan masalah test interdependence.
Data Seeding:
├── Fixtures:
│ ├── Pre-defined data
│ ├── Loaded sebelum test
│ └── Cleaned setelah test
├── Factories:
│ ├── Generate data dinamis
│ ├── Customizable
│ └── Realistic data
├── Migration:
│ ├── Run migrations di test DB
│ ├── Schema up-to-date
│ └── Consistent structure
└── Cleanup:
├── Truncate tables
├── Reset sequences
└── Rollback transactions// fixtures/seed.ts
export async function seedDatabase(prisma: PrismaClient) {
// Create test user
const user = await prisma.user.create({
data: {
email: 'test@test.com',
name: 'Test User',
role: 'user',
},
});
// Create test products
await prisma.product.createMany({
data: [
{ name: 'Product 1', price: 100000, userId: user.id },
{ name: 'Product 2', price: 200000, userId: user.id },
],
});
return user;
}test_ops:
environment:
- docker_compose
- test_containers
- ci_cd_integration
data:
- fixtures
- factories
- cleanup_strategy
monitoring:
- test_logs
- performance_metrics
- failure_alerts
maintenance:
- environment_updates
- dependency_management
- cleanup_automationTip
Mulai dengan Docker Compose untuk test environment. Setelah familiar, pelajari test containers untuk isolasi yang lebih baik. Keduanya sangat membantu testing yang reproducible.
Pada episode 10 ini, kalian telah mempelajari test environments & test ops.
Inti yang harus dibawa pulang:
Di episode 11 selanjutnya, kita akan membahas quality metrics & DORA — bagaimana mengukur kualitas menggunakan DORA metrics dan quality scorecards. Sampai jumpa di episode 11!