← Mundo bit ByteQualidade e Teste de Software
Professor Ronaldo Lavestein
Especificar pelo teste
Etapa 12

Teste antes do código

Até aqui, quase sempre partimos de uma regra já implementada e depois escrevemos testes. Agora a Cantina Horizonte recebeu uma regra nova. E se o primeiro código que escrevermos for justamente o teste?

Uma novidade na cantina

A escola começou a aceitar encomendas maiores para reuniões e eventos internos. Nesses pedidos existe uma taxa de entrega interna de R$ 5,00.

A nova regra é simples: pedidos com subtotal a partir de R$ 100,00 não pagam a taxa de entrega.

A função que calcula essa taxa ainda não existe.

Normalmente poderíamos implementá-la e só depois testar. Mas existe outra maneira de trabalhar: transformar primeiro a regra em um exemplo executável.

Antes de programar, deixe o comportamento claro

Vamos começar com três situações que deixam a fronteira da regra visível:

SubtotalTaxa esperadaPor quê?
R$ 99,99R$ 5,00Ainda está abaixo do limite.
R$ 100,00R$ 0,00É exatamente o início da gratuidade.
R$ 150,00R$ 0,00Está acima do limite.

Perceba que estamos reaproveitando uma técnica anterior: análise de valores-limite. TDD não substitui o que aprendemos; ele pode usar esse raciocínio.

Escrevendo o primeiro teste

Continue na mesma cópia do projeto usada na Etapa 11. Na pasta tests, crie o arquivo test_entrega.py com este conteúdo:

from backend.app import calcular_taxa_entrega


def test_subtotal_de_100_deve_ter_entrega_gratis():
    assert calcular_taxa_entrega(100) == 0

Agora execute o pytest do mesmo modo que na etapa anterior.

python -m pytest

Se estiver no Windows e não tiver ativado o ambiente virtual, use .venv\Scripts\python.exe -m pytest.

A função calcular_taxa_entrega ainda não existe. Por isso, o pytest pode mostrar um erro de importação durante a coleta dos testes, em vez de uma comparação marcada apenas como FAILED. Isso é esperado neste primeiro passo: o comportamento que o teste pede ainda não existe.

O importante é saber por que a execução está vermelha. Não queremos qualquer erro; queremos uma execução que não fica verde porque o comportamento desejado ainda não foi implementado.

RED: primeiro vemos a execução falhar pelo motivo esperado

No ciclo mais conhecido do TDD, o primeiro estado costuma ser chamado de RED, palavra inglesa para “vermelho”. Ele representa uma situação em que o teste ainda não pode ser satisfeito.

Se a execução falhar por caminho de arquivo errado, erro de digitação ou outro ruído que não tenha relação com a regra nova, corrija esse ruído antes de continuar.

GREEN: escrever apenas o suficiente para passar

Abra backend/app.py e acrescente a função abaixo junto das demais funções de regra:

def calcular_taxa_entrega(subtotal):
    if subtotal >= 100:
        return 0
    return 5

Execute os testes novamente. Quando o novo teste passar, chegamos ao estado chamado GREEN, “verde”: o comportamento testado foi atendido.

Mas um teste só ainda é pouco

No mesmo arquivo tests/test_entrega.py, acrescente:

def test_abaixo_de_100_deve_cobrar_taxa():
    assert calcular_taxa_entrega(99.99) == 5


def test_acima_de_100_deve_ter_entrega_gratis():
    assert calcular_taxa_entrega(150) == 0

Agora temos uma pequena rede de proteção em torno da regra.

REFACTOR: melhorar sem mudar o comportamento

Depois que os testes passam, podemos melhorar a estrutura do código sem alterar o resultado esperado. Essa etapa é chamada de REFACTOR, de refactoring, ou refatoração.

Por exemplo, podemos retirar números importantes de dentro da função:

TAXA_ENTREGA = 5
LIMITE_ENTREGA_GRATIS = 100


def calcular_taxa_entrega(subtotal):
    if subtotal >= LIMITE_ENTREGA_GRATIS:
        return 0
    return TAXA_ENTREGA

Depois da mudança, execute a suíte novamente. Se continuar verde, temos evidência de que a refatoração preservou aqueles comportamentos.

Agora podemos dar nome ao ciclo

Desenvolvimento Guiado por Testes (Test-Driven Development — TDD)

É uma abordagem de desenvolvimento em que escrevemos um teste para um pequeno comportamento antes de implementar esse comportamento, fazemos o teste passar e então melhoramos o código mantendo os testes verdes.

RED · teste não passa→GREEN · teste passa→REFACTOR · melhorar→repetir

TDD não significa “escrever qualquer teste primeiro”

O teste precisa representar um comportamento pequeno e compreensível. Se começarmos com uma enorme sequência que envolve tela, servidor, banco e várias regras ao mesmo tempo, teremos dificuldade para saber o que realmente estamos guiando.

Por isso, TDD costuma funcionar melhor em passos pequenos.

TDD também não garante tudo

Podemos ter vários testes verdes e ainda deixar problemas de usabilidade, desempenho, integração ou requisitos mal compreendidos.

TDD ajuda a desenvolver comportamentos com feedback rápido. Não é um certificado de que o produto inteiro está correto.

Isso se conecta ao que já vimos sobre níveis de teste: uma função pode passar sozinha e ainda falhar quando precisa conversar com outras partes.

Prática · uma nova regra antes do código

A cantina propõe outra mudança:

Pedidos com subtotal a partir de R$ 25,00 recebem R$ 5,00 de desconto promocional.

Crie primeiro os testes para R$ 24,99, R$ 25,00 e R$ 40,00. Dê um nome claro à nova função, execute para obter o RED esperado, implemente o mínimo necessário no backend/app.py, alcance o GREEN e só então refatore se houver algo que possa ficar mais claro.

O teste passou. O sistema inteiro está protegido?

A função pode calcular corretamente a taxa ou o desconto, mas a tela pode enviar dados errados, o servidor pode interpretar outra estrutura e o banco pode não registrar o resultado.

Como testar quando o problema está na conversa entre as partes do sistema?

A seguir: testar interface, servidor e banco juntos

Vamos observar a comunicação entre interface, servidor e banco de dados, conhecer uma API e testar requisições diretamente, sem depender da tela.

Antes de seguir

Você deve conseguir explicar:

  • o que significa Desenvolvimento Guiado por Testes (TDD);
  • o papel de RED, GREEN e REFACTOR no ciclo;
  • por que um teste pode começar vermelho porque o comportamento ainda não existe;
  • por que TDD não substitui testes de integração, sistema e características não funcionais.