Il ciclo Red‑Green‑Refactor del TDD converte requisiti incerti in passi piccoli e verificabili: scrivi il test che fallisce, implementa il minimo per farlo passare e poi refattorizza con i test verdi come rete di sicurezza. È una pratica di progettazione utile per team React/TypeScript che vogliono qualità, prevedibilità e feedback rapido.
November 29, 2025 (10mo ago) — last updated August 27, 2026 (1mo ago)
TDD Red‑Green‑Refactor in React + TypeScript
Scopri il ciclo Red‑Green‑Refactor del TDD con esempi pratici in React e TypeScript, consigli di adozione e benefici per la qualità del codice.
← Back to blog
TDD: Red‑Green‑Refactor in React + TypeScript
Sommario: Padroneggia il ciclo Red‑Green‑Refactor del TDD con esempi pratici in React/TypeScript, consigli di adozione e benefici misurabili per la qualità del codice.
Introduzione
Il ciclo Red‑Green‑Refactor del Test‑Driven Development (TDD) trasforma requisiti incerti in passi piccoli e verificabili. Si inizia scrivendo un test che fallisce (Red), si implementa il minimo necessario per farlo passare (Green) e si pulisce il codice mantenendo i test verdi (Refactor). Questo approccio guida la progettazione, riduce il rischio di regressioni e migliora la manutenibilità fin dall’inizio4.
Perché il TDD è progettazione oltre che testing
Il TDD non è solo una strategia di verifica: è una pratica di progettazione che favorisce progressi incrementali e feedback rapido. Pensare prima all’uso e poi all’implementazione aiuta i team a mantenere un ritmo costante su codebase complesse e fornisce documentazione eseguibile utile per l’onboarding1.
Le tre fasi del ciclo e come applicarle subito
- Red (test che fallisce): definisci un singolo comportamento osservabile e scrivi il test che lo verifica. Il test deve fallire per dimostrare che stai coprendo una nuova funzionalità.
- Green (farlo passare): scrivi il codice minimo per far passare il test. Priorità alla semplicità e alla velocità di feedback.
- Refactor (migliorare il codice): con i test verdi come rete di sicurezza, rinomina, semplifica e rimuovi duplicazioni.
Non saltare il refactor: accumulare codice non rifattorizzato significa accumulare debito tecnico che rallenterà il team.
Esempio pratico: LikeButton in React + TypeScript
Applichiamo il ciclo costruendo un componente LikeButton con React, TypeScript e Jest. L’esempio mostra come il TDD guidi il design e garantisca comportamenti prevedibili.
Red: scrivere il primo test
Requisito iniziale: il componente si renderizza senza crash e mostra “Like”. Scrivi il test prima del 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()
})
})
Eseguendo i test, il caso fallirà perché il componente non esiste ancora: questa è la fase Red.
Green: il minimo per far passare il test
Crea il componente minimo necessario.
// LikeButton.tsx
import React from "react"
const LikeButton = () => {
return <button>Like</button>
}
export default LikeButton
Esegui i test: ora dovrebbero essere verdi.
Refactor: migliorare l’implementazione
Aggiungi tipi e struttura per rendere il componente pronto a evolvere.
// LikeButton.tsx (refactored)
import React, { FC } from "react"
type LikeButtonProps = {}
const LikeButton: FC<LikeButtonProps> = () => {
return <button>Like</button>
}
export default LikeButton
I test restano verdi e ora hai una base più chiara per aggiungere funzionalità.
Iterazione: aggiungere il comportamento al clic
Nuovo requisito: al clic il testo diventa “Liked” e il bottone viene disabilitato.
// LikeButton.test.tsx (aggiunta)
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()
})
Implementazione minima:
// LikeButton.tsx (implementazione del clic)
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
Ripeti il ciclo per ogni requisito: piccoli passi protetti dai test.
Benefici tecnici e di business
Il TDD porta benefici misurabili: riduce le regressioni, abbassa i costi di supporto e rende le modifiche future meno rischiose2. Team disciplinati nel testing osservano miglioramenti nelle metriche operative, come lead time e tempo di ripristino dagli incidenti3.
Ridurre difetti e costi di manutenzione
Scrivere test prima dell’implementazione limita il codice superfluo in produzione e crea una rete di sicurezza che riduce le regressioni, abbassando il costo totale di possesso del software nel tempo2.
Accelerare l’onboarding e la prevedibilità
Una suite di test ben curata è documentazione eseguibile: i nuovi sviluppatori possono eseguire i test per capire il comportamento atteso, riducendo i tempi di ramp‑up e migliorando la pianificazione con gli stakeholder1.
Anti‑pattern comuni e come evitarli
Test di integrazione travestiti da unit test
Problema: il test esercita troppe dipendenze e diventa lento e fragile. Soluzione: isola l’unità con mock, stub o fake; riserva i test di integrazione a suite separate e più lente.
Testare l’implementazione invece del comportamento
Problema: i test verificano dettagli interni e si rompono alla refactor. Soluzione: testa l’API pubblica e gli effetti osservabili.
Saltare il refactor
Problema: si passa alla prossima funzionalità lasciando codice disordinato. Soluzione: considera il refactor un passaggio obbligatorio dopo che i test sono verdi.
Integrare il TDD in team e codebase legacy
Adottare il TDD è un cambiamento culturale oltre che tecnico. Rendi i test parte della Definition of Done, promuovi pair programming e sessioni pratiche per diffondere il know‑how.
Promuovere il TDD nel team
- Pair programming per trasmettere il ciclo Red‑Green‑Refactor.
- Mob programming per problemi complessi, ruotando chi guida.
- Sessioni hands‑on su feature reali.
Inizia in piccolo: una nuova feature o un bug non critico sono ottimi punti di partenza.
Domare il codice legacy
Quando il codice non ha test, scrivi characterization test per fissare il comportamento corrente. Questi test permettono di refattorizzare con fiducia.
Automazione: CI/CD e qualità
Esegui la suite di test ad ogni commit in CI per avere feedback immediati e impedire regressioni in fase di merge. L’automazione mantiene il ciclo di feedback rapido e affidabile. Per dettagli su test end‑to‑end e pipeline CI/CD, vedi le guide interne: Guida al testing end‑to‑end e Pipeline CI/CD.
Domande rapide
Il TDD sostituisce altri tipi di testing?
No. Il TDD si concentra sui unit test come strumento di progettazione, ma restano necessari test di integrazione e end‑to‑end per convalidare le interazioni e i flussi utente completi.
Come testare codice che usa database o API esterne?
Isola la logica di business usando mock, stub o fake. Mantieni i unit test veloci e scrivi test di integrazione separati per verificare le interazioni reali.
Ha senso testare componenti UI semplici?
Sì: testa il comportamento osservabile — cosa vede e cosa può fare l’utente — evitando di verificare dettagli di implementazione interni.
FAQ essenziali
Quanto tempo per vedere valore dal TDD?
Spesso si notano riduzioni di regressioni e debug più rapidi entro poche sprint, a seconda della disciplina del team3.
Qual è il passo minimo per iniziare?
Inizia con un singolo requisito: scrivi il test che fallisce, implementa il minimo per farlo passare e poi refattorizza.
Come convincere gli stakeholder?
Mostra risparmi a lungo termine con esempi concreti di incidenti evitati e metriche dalla CI, come tassi di regressione e tempo medio di ripristino3.
Domande e risposte rapide
Q: Qual è il primo passo pratico per iniziare col TDD in un progetto React?
A: Scegli una piccola feature non critica, scrivi il test che fallisce e procedi con Red‑Green‑Refactor.
Q: Il TDD rallenta lo sviluppo all’inizio?
A: All’inizio può sembrare più lento, ma riduce il tempo speso su bug e regressioni, portando guadagni a medio termine2.
Q: Come affrontare legacy code senza test?
A: Scrivi characterization test per il comportamento corrente e refattorizza gradualmente con sicurezza.
L'AI scrive codice.Tu lo fai durare.
Nell'era dell'accelerazione AI, il codice pulito non è solo una buona pratica — è la differenza tra sistemi che si scalano e codebase che collassano sotto il loro stesso peso.