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.
November 29, 2025 (9mo ago) — last updated August 6, 2026 (20d 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
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

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
| Fase | Propósito | Objetivo do desenvolvedor |
|---|---|---|
| Red | Definir requisito e validar o teste | Escrever um teste pequeno que falhe |
| Green | Satisfazer o requisito | Adicionar o código mínimo para passar o teste |
| Refactor | Melhorar qualidade interna | Remover 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

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

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

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