November 29, 2025 (8mo ago) — last updated August 6, 2026 (5d ago)

TDD Red‑Green‑Refactor: Guia Prático React/TypeScript

Aprenda o ciclo Red‑Green‑Refactor do TDD com exemplos em React/TypeScript, refatoração segura e práticas que tornam o código mais testável e previsível.

← Back to blog
Cover Image for TDD Red‑Green‑Refactor: Guia Prático React/TypeScript

O ciclo Red‑Green‑Refactor do TDD converte design em passos pequenos e verificáveis: escreva um teste que falha (Red), implemente o mínimo para passar (Green) e refatore com confiança. Repetir esse ciclo reduz incertezas, torna entregas previsíveis e diminui riscos desde as primeiras iterações do projeto1.

TDD Red‑Green‑Refactor: Guia Prático React/TypeScript

Resumo: Domine o ciclo Red‑Green‑Refactor do TDD com exemplos em React e TypeScript, práticas de refatoração e testes que tornam o código previsível e testável.

Introdução

O ciclo Red‑Green‑Refactor do Test‑Driven Development (TDD) transforma design em passos pequenos e verificáveis: escreva um teste que falha (Red), implemente o mínimo para fazê‑lo passar (Green) e refatore com segurança (Refactor). Repetir esse ciclo converte incerteza em progresso previsível e reduz riscos desde as primeiras iterações do projeto1.

O ritmo do desenvolvimento guiado por testes

Diagrama do ciclo Red‑Green‑Refactor

TDD é mais do que escrever testes: é uma técnica de design. Escrever o teste primeiro força você a pensar em como o código será usado antes de implementá‑lo, reduzindo suposições e permitindo entregas em pequenos passos confiáveis.

As três fases, em poucas palavras

  • Fase Red (teste falhando): escreva um teste automatizado que descreva o menor comportamento útil. O teste deve falhar porque a implementação ainda não existe.
  • Fase Green (fazer passar): implemente a menor quantidade de código necessária para satisfazer o teste. Priorize simplicidade para evitar over‑engineering.
  • Fase Refactor (melhorar o código): com os testes passando como rede de segurança, limpe nomes, remova duplicação e melhore a estrutura mantendo o comportamento.

Não pule a refatoração; ela evita acúmulo de dívida técnica e facilita mudanças futuras.

Resumo do ciclo

FasePropósitoObjetivo do desenvolvedor
RedDefinir requisito e validar o testeEscrever um teste pequeno que falhe
GreenSatisfazer o requisitoAdicionar o código mínimo para passar o teste
RefactorMelhorar qualidade internaRemover duplicação e esclarecer intenção

Adotar essa cadência ajuda equipes a avançar de forma previsível e a melhorar colaboração e qualidade ao longo do tempo1.

Percorrendo o ciclo TDD na prática

Fluxo do processo TDD

Exemplo prático: um componente LikeButton usando TypeScript, React e Jest. O fluxo ilustra como TDD orienta design e comportamento observável.

Fase Red: definir o primeiro requisito

Requisito inicial: o componente renderiza sem travar e exibe “Like”. Escrevemos o teste antes do componente.

// LikeButton.test.tsx
import React from "react";
import { render, screen } from "@testing-library/react";
import LikeButton from "./LikeButton";

describe("LikeButton", () => {
  it("renders a button with the initial text \"Like\"", () => {
    render(<LikeButton />);
    const likeButton = screen.getByRole("button", { name: /like/i });
    expect(likeButton).toBeInTheDocument();
  });
});

Executar o teste falha porque o componente ainda não existe. Esta é a fase Red — exatamente o que queremos.

Fase Green: o suficiente para passar

Crie o componente mínimo para satisfazer o teste.

// LikeButton.tsx
import React from "react";

const LikeButton = () => {
  return <button>Like</button>;
};

export default LikeButton;

Execute os testes novamente e eles passam. Missão cumprida para este ciclo.

Fase Refactor: polir a implementação

Agora limpe o código. Adicione tipos e estabeleça um padrão para expansão futura.

// LikeButton.tsx (refatorado)
import React, { FC } from "react";

type LikeButtonProps = {};

const LikeButton: FC<LikeButtonProps> = () => {
  return <button>Like</button>;
};

export default LikeButton;

Os testes continuam passando. A rede de segurança permite melhorar o código com confiança.

Iteração: clicar no botão

Novo requisito: clicar no botão altera seu texto para “Liked” e o desabilita para evitar múltiplos cliques. Comece com um teste que falha.

// LikeButton.test.tsx
import { fireEvent } from "@testing-library/react";

it("changes text to \"Liked\" and becomes disabled when clicked", () => {
  render(<LikeButton />);
  const likeButton = screen.getByRole("button", { name: /like/i });
  fireEvent.click(likeButton);
  expect(likeButton).toHaveTextContent("Liked");
  expect(likeButton).toBeDisabled();
});

Implemente o comportamento mínimo para passar no teste.

// LikeButton.tsx
import React, { FC, useState } from "react";

type LikeButtonProps = {};

const LikeButton: FC<LikeButtonProps> = () => {
  const [liked, setLiked] = useState(false);
  const handleClick = () => setLiked(true);
  return (
    <button onClick={handleClick} disabled={liked}>
      {liked ? "Liked" : "Like"}
    </button>
  );
};

export default LikeButton;

Execute a suíte e tudo fica verde. Repita: um requisito pequeno por vez, protegido por testes.

O caso de negócio para qualidade de código

Balança comparando sem TDD e com TDD

Os benefícios técnicos do TDD se traduzem em valor de negócio. Menos defeitos em produção significam custos de suporte menores, menor churn de clientes e melhor reputação. Quando defeitos são detectados cedo, custam menos para corrigir; equipes podem dedicar mais tempo a entregar funcionalidades que geram valor2.

Reduzindo defeitos pós‑release e custos de manutenção

Escrever testes antes do código força a adicionar apenas o que é necessário para satisfazer requisitos testáveis. Isso cria uma rede de segurança robusta e reduz regressões. Estudos empíricos mostram melhorias mensuráveis de qualidade e redução do esforço de depuração para equipes que aplicam TDD consistentemente2.

Acelerando o onboarding e melhorando a previsibilidade

Uma suíte de testes funciona como documentação executável. Novos desenvolvedores podem rodar os testes para entender o comportamento esperado do sistema em vez de depender de documentação desatualizada. Isso encurta o tempo de ramp‑up e reduz a carga sobre engenheiros seniores. Práticas de TDD também tornam estimativas e acompanhamento de progresso mais previsíveis, o que melhora o planejamento com stakeholders e processos de entrega automatizados3.

Armadilhas comuns do TDD e como evitá‑las

TDD é simples de explicar, mas sutil de dominar. Os anti‑padrões abaixo costumam minar os benefícios.

Testes de integração embalados como unitários

Problema: o teste acaba exercitando muitas dependências — componentes, serviços, clientes de API e bancos de dados. O teste fica lento e frágil.

Solução: teste uma única unidade em isolamento. Use mocks, stubs e fakes para dependências externas. Se precisar de cobertura de integração, escreva testes de integração separados que rodem em uma suíte distinta.

Um teste unitário verdadeiro não deve tocar a rede, o sistema de arquivos ou um banco de dados real; sua velocidade e confiabilidade permitem refatorar com segurança4.

Testar comportamento em vez de implementação

Problema: os testes afirmam detalhes internos em vez do comportamento público. Testes quebram quando internals mudam, mesmo que o comportamento esteja correto.

Solução: foque na API pública e nos efeitos observáveis. Pergunte: dado este input, qual é o output esperado? Testes que verificam comportamento resistem a refatorações e continuam sendo documentação valiosa.

Pular a refatoração

Problema: desenvolvedores vão direto para a próxima funcionalidade depois de fazer os testes passarem, deixando implementações bagunçadas.

Solução: trate a refatoração como etapa obrigatória. Com os testes passando, pequenas limpezas são seguras e evitam acúmulo de problemas.

Integrando TDD à sua equipe e ao código legado

Equipe trabalhando com código legado

Adotar TDD é mudança cultural e técnica. Incentive aprendizado prático, inclua testes na Definição de Pronto e celebre vitórias orientadas por testes.

Promovendo TDD na equipe

Formas práticas de ganhar adesão:

  • Pair programming para guiar colegas pelo ciclo Red‑Green‑Refactor.
  • Mob programming para problemas complexos, rodiziando quem dirige para espalhar conhecimento.
  • Sessões de aprendizado que demonstrem TDD na base de código.

Comece pequeno e deixe que ganhos cedo se tornem prova do valor.

Domando código legado com testes de caracterização

Quando o código não tem testes e é arriscado de alterar, escreva testes de caracterização para documentar o comportamento atual. Esses testes permitem refatorar ou adicionar funcionalidades com confiança.

Automatizando qualidade com pipelines CI/CD

Execute a suíte de testes em cada commit no CI. Isso fornece feedback imediato, impõe gates de qualidade e torna a passagem dos testes obrigatória antes do merge. A automação mantém o loop de feedback rápido e confiável3. Integre os testes ao seu pipeline de CI e adicione regras de merge para proteger a main branch.

Perguntas frequentes rápidas

O TDD substitui outros tipos de testes?

Não. TDD foca em testes unitários como ferramenta de design, mas você ainda precisa de testes de integração e end‑to‑end para validar interações entre componentes e fluxos completos de usuário.

Como usar TDD com bancos de dados ou APIs externas?

Isole dependências externas usando mocks, stubs ou fakes. Teste a lógica em isolamento e mantenha testes de integração reais em uma suíte separada.

Vale a pena testar componentes simples de UI?

Sim, quando o teste verifica comportamento observável. Testes que afirmam o que o usuário vê e faz são úteis e resistentes a refatoração.

Perguntas e respostas — resumo em 3 pontos

P: Quanto tempo até minha equipe ver valor com TDD?

A: Ganhos aparecem rapidamente na redução de regressões; pequenas vitórias geralmente surgem em poucos sprints.

P: Qual é o menor primeiro passo para adotar TDD?

A: Exija um teste que falhe antes de implementar uma funcionalidade nova ou um bug não crítico, e imponha a refatoração.

P: Como convencer stakeholders a investir em testes?

A: Mostre economias a longo prazo — menos incidentes em produção e custos de manutenção menores — e exemplos concretos de problemas evitados.


Perguntas e respostas adicionais

Q: Como começo TDD em um projeto React existente?

R: Identifique componentes pequenos e críticos, escreva testes de caracterização para o comportamento atual e comece a portar pequenas funcionalidades do código legado para desenvolvimento guiado por testes. Integre os testes ao CI e crie regras de merge que validem a suíte.

Q: Quais métricas acompanhar para justificar TDD?

R: Monitore defeitos em produção, tempo médio para correção (MTTR), taxa de regressões por release e cobertura de testes nas áreas críticas. Use esses dados para demonstrar impacto de custo e qualidade.

Q: Como escrever testes que sejam rápidos e confiáveis?

R: Mantenha testes unitários isolados, evite I/O e redes em unidades de teste, use mocks para dependências e separe testes de integração em outra suíte que rode menos frequentemente.

Q&A Rápida — 3 perguntas curtas

Q: Por onde começo se nunca usei TDD?

A: Escreva um teste simples que falhe antes de implementar qualquer mudança pequena e faça o ciclo Red‑Green‑Refactor. Use pair programming para acelerar aprendizado.

Q: Como o TDD ajuda com bugs em produção?

A: Testes contínuos detectam regressões cedo, reduzindo defeitos em releases e o esforço de correção depois do deploy2.

Q: Preciso de ferramenta X para adotar TDD?

A: Não. Comece com sua stack atual (por exemplo, Jest e Testing Library para React). Integre ao CI e adote boas práticas de isolamento e refatoração.

1.
Digital.ai, “State of Agile Report,” https://digital.ai/resource-center/state-of-agile-report
2.
Basili, Victor R., et al., “An Empirical Study on the Effects of Test-Driven Development,” https://link.springer.com/article/10.1007/s10664-015-9378-2
3.
Google Cloud, “State of DevOps Report,” https://cloud.google.com/devops/state-of-devops
4.
Martin Fowler, “TestDrivenDevelopment,” https://martinfowler.com/bliki/TestDrivenDevelopment.html
← Back to blog
🙋🏻‍♂️

IA escreve código.
Você faz durar.

Na era da aceleração da IA, código limpo não é apenas uma boa prática — é a diferença entre sistemas que escalam e bases de código que entram em colapso sob seu próprio peso.