# Docker para QA: Containers para Testes e Ambientes

**Meta Description:** Aprenda a usar Docker para QA: imagens otimizadas, docker-compose, multi-stage builds, e como containerizar sua suite de testes.

---

## 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

```dockerfile
# 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

```dockerfile
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

```yaml
# 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

```yaml
# 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

```python
# 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

```yaml
# 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:

1. **Multi-stage builds** - Imagens otimizadas
2. **Docker Compose** - Ambientes completos
3. **Testcontainers** - DBs containerizados para testes
4. **Layer caching** - Builds mais rápidos
5. **CI integration** - Automação simplificada
