Membangun test environment yang stabil: containerized environments, database seeds, state reset, dan orchestration untuk reproducible tests

Setelah di episode 19 kita menguji auth flows, pada episode ini kita membahas fondasi test suite yang reliable: test environment. Environment yang tidak stabil menyebabkan flaky tests tanpa akhir.
# docker-compose.test.yml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgresql://test:test@db:5432/testdb
- REDIS_URL=redis://redis:6379
- NODE_ENV=test
depends_on:
- db
- redis
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: testdb
POSTGRES_USER: test
POSTGRES_PASSWORD: test
ports:
- "5432:5432"
volumes:
- ./seeds:/docker-entrypoint-initdb.d
redis:
image: redis:7-alpine
ports:
- "6379:6379"# Dockerfile.playwright
FROM mcr.microsoft.com/playwright:v1.50.0-noble
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["npx", "playwright", "test"]// seeds/seed.ts
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
export async function seed() {
// Clean database
await prisma.user.deleteMany();
await prisma.product.deleteMany();
// Seed users
await prisma.user.createMany({
data: [
{ email: 'user1@test.com', name: 'User 1', password: 'hashed' },
{ email: 'user2@test.com', name: 'User 2', password: 'hashed' },
],
});
// Seed products
await prisma.product.createMany({
data: [
{ name: 'Product A', price: 29.99, stock: 100 },
{ name: 'Product B', price: 49.99, stock: 50 },
],
});
}
seed().then(() => prisma.$disconnect());// Reset database sebelum test suite
test.beforeAll(async () => {
await seed();
});
// Reset setelah test suite
test.afterAll(async () => {
await cleanup();
});// Wrap test dalam transaction, rollback setelah test
test('user creation', async ({ page }) => {
const tx = await prisma.$transaction(async () => {
// Test code...
await prisma.user.create({ data: { email: 'test@test.com' } });
});
// Transaction automatically rolled back
});// Reset via API endpoint
test.beforeEach(async ({ request }) => {
await request.post('/api/test/reset');
});Stability Checklist:
├── Isolated test data (per-test atau per-suite)
├── Deterministic seeds (same seed = same data)
├── Cleanup after tests
├── Mock external services
├── Fixed timestamps (freeze time)
├── Containerized environment (same everywhere)
└── Health checks sebelum test mulaiNote
Test environment harus identik di lokal dan CI. Gunakan Docker untuk memastikan konsistensi.
# 1. Jalankan test environment
docker-compose -f docker-compose.test.yml up -d
# 2. Seed database
npm run seed
# 3. Jalankan tests
npx playwright test
# 4. Cleanup
docker-compose -f docker-compose.test.yml down -vDi episode 21 selanjutnya kita akan membahas AI-assisted test generation — menggunakan AI untuk generate tests, self-healing, dan triage. Sampai jumpa di episode 21!