Por Que Docker para QA?
- Ambientes consistentes – Same in dev, CI, prod
- Isolamento – Testes não afetam sistema host
- Reproducibilidade – Resultados consistentes
- Escalabilidade – Múltiplos containers de teste
- CI/CD integration – Fáceis de automatizar
Dockerfile para Testes
Multi-Stage Build
# syntax=docker/dockerfile:1
# Stage 1: Build
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# Stage 2: Test
FROM node:18-alpine AS test
WORKDIR /app
# Copy dependencies only (layer caching)
COPY package*.json ./
RUN npm ci
# Copy source
COPY . .
# Install test dependencies
RUN npm ci --prefix .
# Copy built artifacts
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
# Run tests
CMD ["npm", "test"]
# Stage 3: Production
FROM node:18-alpine AS production
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package*.json ./
USER node
EXPOSE 8080
CMD ["node", "dist/index.js"]
Python Tests
FROM python:3.11-slim
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends
build-essential
libpq-dev
&& rm -rf /var/lib/apt/lists/*
# Copy requirements first (layer caching)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy application
COPY . .
# Run tests with coverage
CMD ["pytest", "-v", "--cov=src", "--cov-report=xml", "--cov-report=html"]
Docker Compose para Ambientes
Desenvolvimento Local
# docker-compose.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
environment:
- NODE_ENV=development
- DATABASE_URL=postgres://test:test@db:5432/test
- REDIS_URL=redis://cache:6379
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
volumes:
- .:/app
- /app/node_modules
command: npm run dev
db:
image: postgres:15-alpine
environment:
POSTGRES_DB: test
POSTGRES_USER: test
POSTGRES_PASSWORD: test
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./scripts/init-db.sql:/docker-entrypoint-initdb.d/init.sql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U test -d test"]
interval: 5s
timeout: 5s
retries: 5
cache:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
test:
build:
context: .
dockerfile: Dockerfile.test
environment:
- DATABASE_URL=postgres://test:test@db:5432/test
- REDIS_URL=redis://cache:6379
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
volumes:
- ./test-results:/app/test-results
command: pytest -v --junitxml=/app/test-results/results.xml
volumes:
postgres_data:
redis_data:
CI Environment
# docker-compose.ci.yml
version: '3.8'
services:
app:
build:
context: .
target: test
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_started
environment:
DATABASE_URL: postgres://test:test@postgres:5432/test
REDIS_URL: redis://redis:6379
command: pytest -v --cov=src --cov-report=xml --cov-fail-under=80
postgres:
image: postgres:15-alpine
environment:
POSTGRES_DB: test
POSTGRES_USER: test
POSTGRES_PASSWORD: test
healthcheck:
test: ["CMD-SHELL", "pg_isready -U test"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
Testcontainers
# testcontainers_example.py
import pytest
from testcontainers.postgres import PostgresContainer
from testcontainers.redis import RedisContainer
from testcontainers.compose import DockerCompose
import psycopg2
@pytest.fixture(scope="module")
def postgres():
with PostgresContainer("postgres:15") as pg:
yield pg
@pytest.fixture(scope="module")
def redis():
with RedisContainer("redis:7") as rd:
yield rd
@pytest.fixture
def db_connection(postgres):
conn = psycopg2.connect(postgres.get_connection_url())
yield conn
conn.close()
def test_with_containers(postgres, redis):
"""Test usando bancos containerizados"""
# Use containers
db_url = postgres.get_connection_url()
redis_url = redis.get_connection_url()
# Your test logic here
conn = psycopg2.connect(db_url)
cursor = conn.cursor()
cursor.execute("SELECT version();")
result = cursor.fetchone()
assert "PostgreSQL" in result[0]
Docker para Selenium Grid
# selenium-grid.yml
version: '3.8'
services:
selenium-hub:
image: selenium/hub:4.15
ports:
- "4442:4442"
- "4443:4443"
- "4444:4444"
environment:
SE_EVENT_BUS_HOST: selenium-hub
SE_EVENT_BUS_PUBLISH_PORT: 4442
SE_EVENT_BUS_SUBSCRIBE_PORT: 4443
chrome:
image: selenium/node-chrome:4.15
depends_on:
- selenium-hub
environment:
SE_EVENT_BUS_HOST: selenium-hub
SE_EVENT_BUS_PUBLISH_PORT: 4442
SE_EVENT_BUS_SUBSCRIBE_PORT: 4443
SE_NODE_MAX_SESSIONS: 5
shm_size: '2gb'
firefox:
image: selenium/node-firefox:4.15
depends_on:
- selenium-hub
environment:
SE_EVENT_BUS_HOST: selenium-hub
SE_EVENT_BUS_PUBLISH_PORT: 4442
SE_EVENT_BUS_SUBSCRIBE_PORT: 4443
SE_NODE_MAX_SESSIONS: 3
edge:
image: selenium/node-edge:4.15
depends_on:
- selenium-hub
environment:
SE_EVENT_BUS_HOST: selenium-hub
SE_EVENT_BUS_PUBLISH_PORT: 4442
SE_EVENT_BUS_SUBSCRIBE_PORT: 4443
SE_NODE_MAX_SESSIONS: 3
Conclusão
Docker é essencial para QA moderno. As chaves são:
- Multi-stage builds – Imagens otimizadas
- Docker Compose – Ambientes completos
- Testcontainers – DBs containerizados para testes
- Layer caching – Builds mais rápidos
- CI integration – Automação simplificada
