Testes e qualidade de código

TDD: Ciclo Red-Green-Refactor na prática

“Escrever os testes primeiro? Ainda nem existe código—o que eu testaria?”

4 min de leitura
Imagem de capa de TDD: Ciclo Red-Green-Refactor na prática

“Escrever os testes primeiro? Ainda nem existe código—o que eu testaria?”

Ao conhecer TDD (Test-Driven Development, desenvolvimento orientado a testes), todo mundo pensa isso. A ordem parece invertida, e dá a sensação de dobrar o trabalho sem motivo.

Mas, depois de usá-lo no trabalho por alguns meses, sua perspectiva começa a mudar.

TDD é uma forma de desenvolvimento que repete, em ciclos muito curtos, “teste que falha (Red) → código mínimo que o faz passar (Green) → organização (Refactor)”. O ponto principal é executar esse ciclo rapidamente, de alguns segundos a alguns minutos.

Hoje, vou explicar passo a passo como esse ciclo Red-Green-Refactor funciona na prática.


TDD Red-Green-Refactor: resumo das 3 etapas principais ✍️

Primeiro, veja o ciclo completo de uma só vez.

  1. Red: escrever primeiro um teste para uma funcionalidade que ainda não existe. Naturalmente, ele falha.
  2. Green: escrever apenas o código mínimo necessário para passar no teste. Ele não precisa ser bonito.
  3. Refactor: organizar o código mantendo os testes passando.

É só isso: juntar essas três etapas e repeti-las continuamente.

TDD consiste em percorrer essas três etapas repetidamente
TDD consiste em percorrer essas três etapas repetidamente

O importante é não tornar cada etapa grande demais. Divida-a em partes pequenas: não “a funcionalidade inteira de login”, mas algo como “retornar um erro quando o e-mail estiver vazio”.

Se um ciclo leva 30 minutos, provavelmente não é TDD, mas desenvolvimento com testes adicionados.


Etapa Red: por que escrever código que falha de propósito?

É a parte mais difícil de entender ao aprender TDD. Você sabe que vai falhar, então por que executar?

O motivo é simples. Para confirmar que o teste “falha corretamente”.

Se um teste passa assim que é escrito, pode ser apenas uma casca vazia que não valida nada. Ver a falha primeiro é, na prática, testar o próprio teste.

Como exemplo simples, suponha que vamos criar uma função que soma dois números. O teste vem antes do código.

// add A função ainda não existe. Por isso, este teste falha(Red)
struct AddTests {
    @Test func Adição_1somar2é3() {
        #expect(add(1, 2) == 3)
    }
}

Executando nesse estado, aparece um erro como “cannot find ‘add’ in scope”. Ver essa luz vermelha até me tranquiliza, porque o objetivo fica claro.

A partir daqui, tenho uma única tarefa: transformar essa luz vermelha em verde.

Ver essa luz vermelha deixa clara a próxima tarefa
Ver essa luz vermelha deixa clara a próxima tarefa

Green e Refactor: é aqui que a verdadeira habilidade aparece

O princípio da etapa Green é “manter tudo simples a ponto de dar vergonha”.

Este é o código mais rápido que faz o teste anterior passar.

// O código mínimo que faz o teste passar(Green)
func add(_ a: Int, _ b: Int) -> Int {
    return a + b
}

Parece óbvio, não? Mesmo assim, iniciantes costumam se preocupar com o futuro e tentam adicionar tratamento de exceções, logging e valores de configuração antecipadamente.

O TDD força você a conter esse impulso. A regra é não escrever código que o teste atual não exige.

Só depois que a luz verde acende você passa ao Refactor. É quando ajusta nomes de variáveis e remove duplicações.

O ponto principal é nunca adicionar novas funcionalidades durante o Refactor. Apenas melhore a estrutura mantendo os testes passando.

E se a luz ficar vermelha durante a organização? Basta desfazer o que você acabou de alterar. Os testes garantem que tudo funcionava até alguns instantes atrás.

Graças a essa rede de segurança, a refatoração ficou muito mais ousada.

É essa sensação de transformar a luz vermelha em verde que faz você continuar
É essa sensação de transformar a luz vermelha em verde que faz você continuar

O TDD deixa o desenvolvimento mais lento? 🤔

É a pergunta que mais ouço. Depois de usá-lo, minha resposta foi: “depende”.

Organizei em uma tabela as diferenças que percebi.

Categoria Com TDD Testes escritos depois
Velocidade inicial Um pouco mais lenta Rápida
Momento em que os bugs são encontrados Imediatamente após escrever Muito depois
Custo da refatoração Baixo Alto
Lógica complexa Vantajoso Desvantajoso

Sinceramente, TDD pode parecer trabalhoso ao criar rapidamente uma única tela simples.

Por outro lado, ele fez toda a diferença em lógicas cheias de condições, como pagamentos, acertos e cálculos de descontos. Ao fixar cada caso com testes, deixei de ter medo de alterar o código depois.

No fim, TDD não é uma solução universal; é mais uma ferramenta para controlar a complexidade.


Conclusão

Se TDD parece difícil, não comece de forma grandiosa. Experimente Red-Green-Refactor primeiro com uma única função.

Quando os pequenos ciclos de sucesso se tornam naturais, você começa a entender por que as pessoas não conseguem abandonar esse método. Espero que hoje você acenda a luz vermelha com apenas um teste.

Leitura recomendada