Guida completa a Unit Test, Integration Test e TDD
Test in C#: scrivere codice affidabile con unit test, integration test e TDD
π Introduzione
Nello sviluppo software, uno degli aspetti più trascurati (ma cruciali) è la qualità del codice. Troppo spesso ci si concentra sull’aggiungere nuove funzionalità il più velocemente possibile, trascurando la domanda più importante: "Funziona davvero come dovrebbe?"
Qui entrano in gioco i test automatici, fondamentali per lo sviluppo moderno. In C# e .NET, la scrittura dei test non solo è semplice, ma è parte integrante del ciclo di vita di un progetto professionale.
In questo articolo ti mostrerò:
Perché scrivere test in C#
Quali sono le tipologie più comuni
Un esempio concreto con xUnit
Come organizzare i test nel tuo progetto
Best practice ed errori da evitare
Un'introduzione al Test Driven Development (TDD)
π― Perché scrivere test automatici?
1. Eviti bug e regressioni
Un codice senza test è un terreno minato. Una modifica in una parte dell'app può rompere funzionalità altrove, senza che nessuno se ne accorga. I test fungono da rete di sicurezza.
2. Migliori la qualità del software
Quando scrivi test, sei costretto a pensare al comportamento atteso. Questo porta automaticamente a scrivere codice più pulito, modulare e leggibile.
3. Accelera lo sviluppo a lungo termine
Molti pensano che scrivere test rallenti lo sviluppo. Falso. Dopo un primo investimento iniziale, i test permettono modifiche rapide e sicure, riducendo tempi di debugging.
4. Faciliti il lavoro in team
I test sono documentazione vivente: raccontano come il codice dovrebbe comportarsi. Quando più sviluppatori lavorano su un progetto, questo diventa essenziale.
π§ Tipologie di test in C#
π§ͺ Unit Test
Testano una singola unità di codice (un metodo, una funzione). Sono isolati, veloci e affidabili. Non interagiscono con il database, file system o API.
Esempio: testare che un metodo
Somma(int a, int b)
ritorni il valore corretto.
π Integration Test
Verificano l’integrazione tra componenti: ad esempio tra una repository e il database. Sono più lenti, ma simulano comportamenti reali.
Esempio: verificare che un controller MVC salvi correttamente un record nel database.
π§ End-to-End (E2E)
Simulano l’intero comportamento dell’applicazione: dalla UI al database. Si usano spesso strumenti come Selenium, Playwright o Puppeteer.
βοΈ Esempio pratico con xUnit
Supponiamo di avere una semplice classe:
public class Calcolatrice { public int Somma(int a, int b) => a + b; public int Divisione(int a, int b) { if (b == 0) throw new DivideByZeroException("Divisore non può essere zero."); return a / b; } }
Ecco come possiamo testarla con xUnit:
public class CalcolatriceTests { [Fact] public void Somma_RitornaRisultatoCorretto() { var calc = new Calcolatrice(); var result = calc.Somma(3, 4); Assert.Equal(7, result); } [Fact] public void Divisione_PerZero_LanciaEccezione() { var calc = new Calcolatrice(); Assert.Throws<DivideByZeroException>(() => calc.Divisione(10, 0)); } }
π Come organizzare i test nel tuo progetto
Di solito, si crea un progetto separato:
MyProject/ β βββ MyProject.Core/ βββ MyProject.API/ βββ MyProject.Tests/
Ogni test segue la struttura AAA:
Arrange – preparo i dati
Act – eseguo l’azione
Assert – verifico il risultato
π§° Tool e framework consigliati
xUnit – il più moderno e leggero, ideale per .NET Core.
NUnit – supporta test parametrizzati e più flessibilità.
MSTest – ufficiale Microsoft, integrato in Visual Studio.
Per i mock, consiglio:
Moq
– potente e intuitivoAutoFixture
– per generare oggetti random con valori realistici
β Best Practice
Scrivi test per ogni classe di business
Dai ai test nomi descrittivi (es:
Calcolatrice_SommaDueNumeri_RisultatoCorretto
)Testa anche i casi limite ed eccezioni
Mantieni i test veloci: niente accessi al database in un unit test
Integra i test nel CI/CD (GitHub Actions, Azure DevOps, ecc.)
β Errori da evitare
Scrivere test fragili (dipendenti dall’orario o dal contenuto del database)
Fare test duplicati (es. testare lo stesso metodo in dieci modi inutili)
Testare l’infrastruttura invece della logica di business
Non eseguire i test regolarmente
π Test Driven Development (TDD)
Una menzione speciale merita il Test Driven Development.
Nel TDD, segui questo ciclo:
βοΈ Scrivi un test (che fallisce)
π§ Scrivi il codice minimo per farlo passare
π§Ή Refactoring del codice
Questo approccio forza una progettazione più chiara e modulare.
π Conclusioni
Se vuoi davvero scrivere codice professionale, affidabile e manutenibile, i test non sono un optional. Sono un investimento.
Nel mio lavoro, ogni modulo viene coperto da test:
per evitare regressioni
per garantire coerenza
per documentare il comportamento del software
Scrivere test non è tempo perso. È tempo risparmiato in futuro.