Перейти к содержимому

24. Тестирование с Docker

Тестирование контейнеризованных приложений включает несколько уровней: unit-тесты внутри контейнеров, интеграционные тесты с реальными зависимостями (базой данных, Redis) и end-to-end тесты всего стека.

Окно терминала
# Запустить тесты в контейнере
docker run --rm myapp npm test
# С переменными окружения
docker run --rm \
-e NODE_ENV=test \
-e DATABASE_URL=postgresql://localhost/testdb \
myapp npm test
# Запустить конкретный файл тестов
docker run --rm myapp npx jest src/user.test.js
# С coverage
docker run --rm \
-v $(pwd)/coverage:/app/coverage \
myapp npm run test:coverage
# Dockerfile с этапом тестирования
FROM node:20-alpine AS base
WORKDIR /app
COPY package*.json ./
RUN npm ci
FROM base AS test
COPY . .
RUN npm test # запустить тесты при сборке
# сборка упадёт если тесты не пройдут
FROM base AS production
RUN npm ci --only=production
COPY --from=test /app/dist ./dist # только из успешного test-этапа
CMD ["node", "dist/server.js"]
Окно терминала
# Запустить только до test-этапа
docker build --target test -t myapp:test .
# Сборка упадёт, если тесты не пройдут!
docker build -t myapp:prod .
docker-compose.test.yml
version: '3.8'
services:
tests:
build:
context: .
target: test
environment:
- NODE_ENV=test
- DATABASE_URL=postgresql://testuser:testpass@postgres-test/testdb
- REDIS_URL=redis://redis-test:6379
depends_on:
postgres-test:
condition: service_healthy
redis-test:
condition: service_healthy
command: npm run test:ci
postgres-test:
image: postgres:15-alpine
environment:
POSTGRES_DB: testdb
POSTGRES_USER: testuser
POSTGRES_PASSWORD: testpass
healthcheck:
test: ["CMD-SHELL", "pg_isready -U testuser -d testdb"]
interval: 5s
timeout: 3s
retries: 5
tmpfs:
- /var/lib/postgresql/data # данные в RAM, быстрее
redis-test:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 3
Окно терминала
# Запустить тесты
docker compose -f docker-compose.test.yml up \
--abort-on-container-exit \
--exit-code-from tests
# Очистить после тестов
docker compose -f docker-compose.test.yml down -v

Testcontainers — библиотека, позволяющая запускать реальные Docker-контейнеры из кода тестов:

// Jest + Testcontainers для Node.js
const { PostgreSqlContainer } = require('@testcontainers/postgresql');
const { GenericContainer } = require('testcontainers');
describe('User Service', () => {
let pgContainer;
let redisContainer;
beforeAll(async () => {
// Запустить реальный PostgreSQL в Docker
pgContainer = await new PostgreSqlContainer('postgres:15-alpine')
.withDatabase('testdb')
.withUsername('testuser')
.withPassword('testpass')
.start();
// Запустить Redis
redisContainer = await new GenericContainer('redis:7-alpine')
.withExposedPorts(6379)
.start();
});
afterAll(async () => {
await pgContainer.stop();
await redisContainer.stop();
});
test('should create user', async () => {
const db = await connectToDatabase(pgContainer.getConnectionUri());
const user = await createUser(db, { name: 'Alice' });
expect(user.id).toBeDefined();
});
});
.github/workflows/test.yml
jobs:
test:
strategy:
matrix:
node: [18, 20]
postgres: [14, 15]
runs-on: ubuntu-latest
services:
postgres:
image: postgres:${{ matrix.postgres }}
env:
POSTGRES_PASSWORD: test
options: >-
--health-cmd pg_isready
--health-interval 10s
steps:
- uses: actions/checkout@v4
- run: docker build --target test -t myapp:test .
- run: docker run --rm myapp:test npm test