Testar grátis
8 min leitura Guide 351 of 877

Estratégias de Automação de Testes

Boa automação de testes captura bugs antes dos usuários. Má automação de testes é lenta, flaky e é ignorada. O objetivo é construir automação que equipes confiam e mantêm. Este guia cobre abordagens práticas para automação de testes.

Pirâmide de Testes

NívelVelocidadeCustoCobertura
UnitárioRápidoBaixoMuitos
IntegraçãoMédioMédioAlguns
E2ELentoAltoPoucos

Tipos de Teste

Diferentes Níveis de Teste

PIRÂMIDE DE TESTES
══════════════════

                    ▲
                   /E\      Testes E2E
                  /2E \     (poucos, lentos)
                 /─────\
                /       \
               / Integr- \   Testes de Integração
              /   ação    \  (alguns, médios)
             /─────────────\
            /               \
           /  Testes Unit.   \  Testes Unitários
          /                   \ (muitos, rápidos)
         /─────────────────────\

TESTES UNITÁRIOS:
─────────────────────────────────────
Propósito:
├── Testar funções/classes individuais
├── Isolado de dependências
├── Execução rápida
├── Muitos testes
├── Fundação da automação
└── Maioria dos testes

Características:
├── Rodam em milissegundos
├── Sem dependências externas
├── Sem banco, sem rede
├── Mock de chamadas externas
├── Rodam frequentemente
└── Owned por desenvolvedores

TESTES DE INTEGRAÇÃO:
─────────────────────────────────────
Propósito:
├── Testar interações entre componentes
├── Banco real (instância de teste)
├── Chamadas API reais (para env de teste)
├── Verificar que integrações funcionam
└── Cobertura média

Características:
├── Rodam em segundos
├── Algumas dependências externas
├── Banco de teste
├── Mais realista
├── Rodam no CI
└── Caminhos críticos

TESTES E2E:
─────────────────────────────────────
Propósito:
├── Testar fluxos completos do usuário
├── Browser/app real
├── Verificação end-to-end
├── Apenas jornadas principais
└── Maior confiança

Características:
├── Rodam em minutos
├── Ambiente completo
├── Mais lentos, mais caros
├── Mais flaky (mais partes móveis)
├── Rodam antes de release
└── Cobertura seletiva

Testes Unitários

Fundação da Automação

BOAS PRÁTICAS DE TESTE UNITÁRIO
═══════════════════════════════

BOM TESTE UNITÁRIO:
─────────────────────────────────────
Características:
├── Rápido (< 100ms)
├── Isolado (sem deps externas)
├── Determinístico (mesmo resultado)
├── Focado (testa uma coisa)
├── Legível (documentação)
└── Manutenível

Exemplo:
describe('calcularTotal', () => {
  it('soma preços dos itens', () => {
    const items = [
      { preco: 10, quantidade: 2 },
      { preco: 5, quantidade: 1 }
    ];
    
    expect(calcularTotal(items)).toBe(25);
  });
  
  it('retorna 0 para lista vazia', () => {
    expect(calcularTotal([])).toBe(0);
  });
  
  it('lança erro para item sem preço', () => {
    const items = [{ quantidade: 1 }];
    
    expect(() => calcularTotal(items))
      .toThrow('Item sem preço');
  });
});

─────────────────────────────────────
O QUE TESTAR:
├── Happy path
├── Edge cases
├── Erro handling
├── Boundary conditions
└── Null/undefined

Padrão AAA

PADRÃO ARRANGE-ACT-ASSERT:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ it('aplica desconto corretamente', () => {                │
│   // ARRANGE (Preparar)                                   │
│   const carrinho = criarCarrinho();                       │
│   carrinho.adicionarItem({ preco: 100 });                │
│   const cupom = { tipo: 'percentual', valor: 10 };       │
│                                                             │
│   // ACT (Agir)                                            │
│   carrinho.aplicarCupom(cupom);                           │
│                                                             │
│   // ASSERT (Verificar)                                    │
│   expect(carrinho.total).toBe(90);                        │
│ });                                                         │
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ REGRAS:                                                     │
│ • Uma responsabilidade por teste                          │
│ • Nome descritivo do cenário                              │
│ • Setup claro e mínimo                                    │
│ • Uma asserção principal                                  │
│ • Teste falha por uma razão                              │
└─────────────────────────────────────────────────────────────┘

Testes de Integração

Testando Componentes Juntos

TESTES DE INTEGRAÇÃO:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ QUANDO USAR:                                                │
│ ─────────────                                               │
│ • API endpoints                                           │
│ • Interação com banco de dados                           │
│ • Comunicação entre serviços                             │
│ • Fluxos de negócio críticos                             │
│                                                             │
│ EXEMPLO - TESTE DE API:                                    │
│                                                             │
│ describe('POST /api/usuarios', () => {                    │
│   beforeEach(async () => {                                │
│     await limparBanco();                                  │
│   });                                                       │
│                                                             │
│   it('cria usuário com dados válidos', async () => {     │
│     const response = await request(app)                   │
│       .post('/api/usuarios')                              │
│       .send({                                              │
│         email: 'teste@email.com',                        │
│         nome: 'Teste'                                     │
│       });                                                   │
│                                                             │
│     expect(response.status).toBe(201);                    │
│     expect(response.body.id).toBeDefined();              │
│                                                             │
│     // Verifica no banco                                   │
│     const usuario = await Usuario.findById(              │
│       response.body.id                                     │
│     );                                                       │
│     expect(usuario.email).toBe('teste@email.com');       │
│   });                                                       │
│                                                             │
│   it('rejeita email duplicado', async () => {            │
│     await Usuario.create({                                │
│       email: 'existente@email.com'                       │
│     });                                                     │
│                                                             │
│     const response = await request(app)                   │
│       .post('/api/usuarios')                              │
│       .send({ email: 'existente@email.com' });           │
│                                                             │
│     expect(response.status).toBe(409);                    │
│   });                                                       │
│ });                                                         │
└─────────────────────────────────────────────────────────────┘

Testes E2E

Fluxos Completos

TESTES END-TO-END:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ QUANDO USAR:                                                │
│ ─────────────                                               │
│ • Fluxos críticos de usuário                             │
│ • Jornadas de conversão                                   │
│ • Smoke tests antes de release                           │
│ • Poucos testes, alto valor                              │
│                                                             │
│ O QUE TESTAR (seletivo):                                   │
│ • Login/Signup                                            │
│ • Fluxo de compra                                         │
│ • Funcionalidades core                                    │
│ • Happy paths principais                                  │
│                                                             │
│ EXEMPLO - CYPRESS:                                          │
│                                                             │
│ describe('Fluxo de Compra', () => {                       │
│   it('usuário completa compra', () => {                  │
│     // Login                                               │
│     cy.visit('/login');                                   │
│     cy.get('[data-testid=email]').type('user@test.com');│
│     cy.get('[data-testid=senha]').type('senha123');      │
│     cy.get('[data-testid=submit]').click();              │
│                                                             │
│     // Adicionar ao carrinho                               │
│     cy.visit('/produtos/123');                           │
│     cy.get('[data-testid=add-carrinho]').click();       │
│                                                             │
│     // Checkout                                            │
│     cy.get('[data-testid=ir-checkout]').click();        │
│     cy.get('[data-testid=confirmar]').click();          │
│                                                             │
│     // Verificar                                           │
│     cy.url().should('include', '/confirmacao');          │
│     cy.contains('Pedido confirmado');                    │
│   });                                                       │
│ });                                                         │
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ DICAS PARA E2E:                                             │
│ • Use data-testid para seletores (não classes CSS)       │
│ • Waits explícitos, não implícitos                       │
│ • Teste em ambiente isolado                              │
│ • Dados de teste limpos                                  │
│ • Poucos testes, bem mantidos                           │
└─────────────────────────────────────────────────────────────┘

Lidando com Testes Flaky

Eliminando Instabilidade

COMBATENDO TESTES FLAKY:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ CAUSAS COMUNS:                                              │
│ ──────────────                                              │
│                                                             │
│ ❌ Dependência de timing                                    │
│ ❌ Estado compartilhado entre testes                       │
│ ❌ Dependência de ordem de execução                        │
│ ❌ Race conditions                                          │
│ ❌ Dados de teste não limpos                               │
│ ❌ Ambiente instável                                        │
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ SOLUÇÕES:                                                   │
│ ──────────                                                  │
│                                                             │
│ TIMING:                                                     │
│ ❌ await sleep(1000);                                       │
│ ✅ await waitFor(() => expect(element).toBeVisible());    │
│                                                             │
│ ISOLAMENTO:                                                 │
│ ❌ Testes compartilham dados                               │
│ ✅ Cada teste cria seus dados, limpa depois               │
│                                                             │
│ DETERMINISMO:                                               │
│ ❌ const id = Date.now();                                   │
│ ✅ const id = 'test-id-123';                               │
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ POLÍTICA DE FLAKY:                                          │
│ ─────────────────                                           │
│                                                             │
│ 1. Teste falhou aleatoriamente? QUARENTENA               │
│ 2. Investigar causa raiz                                  │
│ 3. Corrigir ou deletar (não ignorar)                     │
│ 4. Nunca merge com teste flaky                           │
│                                                             │
│ Testes flaky não testados = pior que não ter testes     │
└─────────────────────────────────────────────────────────────┘

Estratégia de Cobertura

O Que Cobrir

ESTRATÉGIA DE COBERTURA:
┌─────────────────────────────────────────────────────────────┐
│                                                             │
│ PRIORIDADES:                                                │
│ ────────────                                                │
│                                                             │
│ 1. CÓDIGO CRÍTICO DE NEGÓCIO                              │
│    • Cálculos financeiros: 100%                          │
│    • Lógica de autorização: 100%                         │
│    • Fluxos de pagamento: 100%                           │
│                                                             │
│ 2. CÓDIGO COMPLEXO                                         │
│    • Algoritmos: Alta cobertura                          │
│    • State machines: Alta cobertura                      │
│    • Parsing/transformação: Alta cobertura               │
│                                                             │
│ 3. CÓDIGO COMUM                                            │
│    • CRUD simples: Cobertura moderada                    │
│    • UI: Cobertura baixa (testes E2E cobrem)            │
│    • Glue code: Cobertura baixa                         │
│                                                             │
│ ─────────────────────────────────────────────────────────── │
│                                                             │
│ METAS DE COBERTURA:                                         │
│                                                             │
│ NÃO: "80% de cobertura em tudo"                           │
│                                                             │
│ SIM: "100% em paths críticos,                             │
│       70% em lógica de negócio,                           │
│       50% overall"                                         │
│                                                             │
│ Cobertura é métrica de input, não de qualidade           │
│ Código coberto ≠ código bem testado                      │
└─────────────────────────────────────────────────────────────┘

Soluções Relacionadas