Procedura dettagliata: Creare ed eseguire unit test per il codice gestito
Articolo
Questo articolo illustra come creare, eseguire e personalizzare una serie di unit test usando il framework di unit test Microsoft per il codice gestito e Visual Studio Esplora test. Si inizia con un progetto C# in fase di sviluppo, si creano test che ne eseguono il codice, eseguono i test ed esaminano i risultati. Modificare quindi il codice del progetto ed eseguire nuovamente i test. Per una panoramica concettuale di queste attività prima di eseguire questi passaggi, vedere nozioni di base di unit test. Per generare test automaticamente dal codice esistente, consulta Creazione di stub per metodi di test unitario dal codice.
Creare un progetto da testare
Apri Visual Studio.
Nella finestra iniziale scegliere Crea un nuovo progetto.
Cercare e selezionare il modello di progetto App console C# per .NET e quindi clic su Avanti.
Nota
Se non viene visualizzato il modello App Console, è possibile installarlo dalla finestra Crea un nuovo progetto. Nella messaggio Non trovi ciò che stai cercando?, scegli il collegamento Installa altri strumenti e funzionalità. Quindi, nel programma di installazione di Visual Studio, scegli il workload sviluppo di applicazioni desktop .NET.
Denominare il progetto Banke quindi fare clic su Avanti.
Scegliere il framework di destinazione consigliato o .NET 8 e quindi cliccare su Crea.
Il progetto Bank viene creato e visualizzato in Esplora soluzioni con il file Program.cs aperto nell'editor di codice.
Nota
Se Program.cs non è aperto nell'editor, fare doppio clic sul file Program.cs in Esplora soluzioni per aprirlo.
Sostituire il contenuto di Program.cs con il codice C# seguente che definisce una classe BankAccount:
Rinominare il file in BankAccount.cs facendo clic con il pulsante destro del mouse e scegliendo Rinomina in Esplora soluzioni.
Nel menu Compila fare clic su Compila soluzione oppure premere CTRL + MAIUSC + B).
È ora disponibile un progetto con metodi che è possibile testare. In questo articolo i test si concentrano sul metodo Debit. Il metodo Debit viene chiamato quando i soldi vengono ritirati da un conto.
Creare un progetto di unit test
Nel menu file selezionare Aggiungi>Nuovo progetto.
Suggerimento
È anche possibile fare clic con il pulsante destro del mouse sulla soluzione in esplora soluzioni e scegliere Aggiungi>Nuovo progetto.
Digitare di test nella casella di ricerca, selezionare C# come linguaggio, quindi selezionare il progetto di test MSTest C# per .NET e quindi fare clic su Avanti.
Nota
In Visual Studio 2019 versione 16.9 il modello di progetto MSTest è Progetto Unit Test.
Denominare il progetto BankTests e fare clic su Avanti.
Scegliere il framework di destinazione consigliato o .NET 8 e quindi cliccare su Crea.
A partire da Visual Studio 2022 versione 17.10, è anche possibile selezionare un test runner. Per il test runner, è possibile scegliere VSTest o MSTest . Per altre informazioni sulla differenza tra i test runner, vedere confronto tra Microsoft.Testing.Platform e VSTest.
Il progetto BankTests viene aggiunto alla soluzione Bank.
Nel progetto BankTests aggiungere un riferimento al progetto Bank.
In Esplora soluzioni, selezionare Dipendenze nel progetto BankTests e quindi scegliere Aggiungi riferimento (o Aggiungi riferimento a progetto) dal menu di scelta rapida.
Nella finestra di dialogo Gestione riferimenti, espandere Progetti, selezionare Soluzionee quindi controllare l'elemento Bank.
Scegliere OK.
Creare la classe di test
Creare una classe di test per verificare la classe BankAccount. È possibile usare il file UnitTest1.cs generato dal modello di progetto, ma assegnare al file e alla classe nomi più descrittivi.
Rinominare un file e una classe
Per rinominare il file, in Esplora soluzioni selezionare il file UnitTest1.cs nel progetto BankTests. Dal menu di scelta rapida scegliere Rinomina (o premere F2) e quindi rinominare il file in BankAccountTests.cs.
Per rinominare la classe, posizionare il cursore su UnitTest1 nell'editor di codice, fare clic con il pulsante destro del mouse e quindi scegliere Rinomina (oppure premere F2). Digitare BankAccountTests e quindi premere INVIO.
Il file BankAccountTests.cs contiene ora il codice seguente:
C#
// The 'using' statement for Test Tools is in GlobalUsings.cs// using Microsoft.VisualStudio.TestTools.UnitTesting;namespaceBankTests
{
[TestClass]
publicclassBankAccountTests
{
[TestMethod]
publicvoidTestMethod1()
{
}
}
}
Aggiungere un'istruzione using
Aggiungere un'istruzione using alla classe di test per poter chiamare il progetto sottoposto a test senza usare nomi completi. Nella parte superiore del file di classe aggiungere:
C#
using BankAccountNS;
Requisiti della classe di test
I requisiti minimi per una classe di test sono:
L'attributo [TestClass] è necessario in qualsiasi classe contenente i metodi di unit test da eseguire in Esplora test.
Ogni metodo di test che si vuole riconoscere in Esplora test deve avere l'attributo [TestMethod].
È possibile avere altre classi in un progetto di unit test che non hanno l'attributo [TestClass] ed è possibile avere altri metodi nelle classi di test che non dispongono dell'attributo [TestMethod]. È possibile chiamare queste altre classi e metodi dai metodi di test.
Creare il primo metodo di test
In questa procedura si scrivono metodi di unit test per verificare il comportamento del metodo Debit della classe BankAccount.
È necessario controllare almeno tre comportamenti:
Se l'importo del debito è valido, il metodo sottrae l'importo di debito dal saldo del conto.
Suggerimento
È possibile eliminare il metodo di TestMethod1 predefinito, perché non verrà usato in questa procedura dettagliata.
Per creare un metodo di test
Il primo test verifica che un importo valido (ovvero uno minore del saldo del conto e maggiore di zero) ritiri l'importo corretto dal conto. Aggiungere il metodo seguente alla classe BankAccountTests:
Il metodo è semplice: configura un nuovo oggetto BankAccount con un saldo iniziale e quindi ritira un importo valido. Usa il metodo Assert.AreEqual per verificare che il saldo finale sia come previsto. Metodi come Assert.AreEqual, Assert.IsTruee altri vengono spesso usati negli unit test. Per altre informazioni concettuali sulla scrittura di un unit test, vedere Scrivere i tuoi test.
Requisiti del metodo di test
Un metodo di test deve soddisfare i requisiti seguenti:
È decorato con l'attributo [TestMethod].
Restituisce void.
Non può avere parametri.
Compilare ed eseguire il test
Nel menu Compila scegliere Compila soluzione oppure premere CTRL + SHIFT + B.
Se Esplora test non è aperto, aprirlo scegliendo Test>Esplora test (o Test>Esplora test di Windows>) dalla barra dei menu superiore oppure premere CTRL + E, T).
Scegliere Esegui tutte le per eseguire il test oppure premere CTRL + R, V).
Durante l'esecuzione del test, la barra di stato nella parte superiore della finestra del Test Explorer è animata. Alla fine dell'esecuzione del test, la barra diventa verde se tutti i metodi di test superano o rosso se uno dei test ha esito negativo.
In questo caso, il test ha esito negativo.
Seleziona il metodo in Test Explorer per visualizzare i dettagli nella parte inferiore della finestra.
Correggere il codice ed eseguire di nuovo i test
Il risultato del test contiene un messaggio che descrive l'errore. Potrebbe essere necessario eseguire il drill-down per visualizzare questo messaggio. Per il metodo AreEqual, il messaggio visualizza ciò che era previsto e ciò che è stato effettivamente ricevuto. Ci si aspettava che il saldo diminuisca, ma invece è aumentato dell'importo del ritiro.
Lo unit test ha scoperto un bug: l'importo del prelievo è aggiunto al saldo del conto quando deve essere sottratto.
Correggere il bug
Per correggere l'errore, nel file BankAccount.cs sostituire la riga:
C#
m_balance += amount;
con:
C#
m_balance -= amount;
Rieseguire il test
In Test Explorer, scegliere Esegui tutto per eseguire nuovamente il test (oppure premere Ctrl + R, V). La barra rossa/verde diventa verde per indicare che il test è stato superato.
superato
superato
Usare unit test per migliorare il codice
Questa sezione descrive come un processo iterativo di analisi, sviluppo di unit test e refactoring consente di rendere il codice di produzione più affidabile ed efficace.
Analizzare i problemi
È stato creato un metodo di test per verificare che un importo valido venga dedotto correttamente nel metodo Debit. Verificare ora che il metodo generi un ArgumentOutOfRangeException se l'importo del debito è:
maggiore del saldo, o
minore di zero.
Creare ed eseguire nuovi metodi di test
Creare un metodo di test per verificare il comportamento corretto quando l'importo del debito è minore di zero:
Utilizzare il metodo ThrowsException per asserire che è stata generata l'eccezione corretta. Questo metodo fa fallire il test a meno che non venga lanciato un ArgumentOutOfRangeException. Se si modifica temporaneamente il metodo sottoposto a test per generare un ApplicationException più generico quando l'importo del debito è minore di zero, il test si comporta correttamente, ovvero ha esito negativo.
Per verificare il caso quando l'importo ritirato è maggiore del saldo, seguire questa procedura:
Creare un nuovo metodo di test denominato Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange.
Copiare il corpo del metodo da Debit_WhenAmountIsLessThanZero_ShouldThrowArgumentOutOfRange al nuovo metodo.
Imposta il debitAmount su un numero maggiore del saldo.
Eseguire i due test e verificare che vengano superati.
Continuare l'analisi
Il metodo sottoposto a test può essere migliorato ulteriormente. Con l'implementazione corrente, non è possibile sapere quale condizione (amount > m_balance o amount < 0) ha causato l'eccezione generata durante il test. Sappiamo solo che un ArgumentOutOfRangeException è stato generato da qualche parte nel metodo . Sarebbe preferibile determinare quale condizione in BankAccount.Debit ha causato la generazione dell'eccezione (amount > m_balance o amount < 0) in modo da essere sicuri che il nostro metodo stia verificando correttamente i suoi argomenti.
Esaminare di nuovo il metodo sottoposto a test (BankAccount.Debit) e notare che entrambe le istruzioni condizionali usano un costruttore ArgumentOutOfRangeException che accetta semplicemente il nome dell'argomento come parametro:
C#
thrownew ArgumentOutOfRangeException("amount");
È possibile usare un costruttore che segnala informazioni molto più complete: ArgumentOutOfRangeException(String, Object, String) include il nome dell'argomento, il valore dell'argomento e un messaggio definito dall'utente. È possibile effettuare il refactoring del metodo sottoposto a test per usare questo costruttore. Ancora meglio, è possibile usare membri di tipo disponibili pubblicamente per specificare gli errori.
Eseguire il refactoring del codice sottoposto a test
Prima di tutto, definire due costanti per i messaggi di errore nell'ambito della classe. Inserire le definizioni nella classe sottoposta a test BankAccount:
C#
publicconststring DebitAmountExceedsBalanceMessage = "Debit amount exceeds balance";
publicconststring DebitAmountLessThanZeroMessage = "Debit amount is less than zero";
Modificare quindi le due istruzioni condizionali nel metodo Debit:
C#
if (amount > m_balance)
{
thrownew System.ArgumentOutOfRangeException("amount", amount, DebitAmountExceedsBalanceMessage);
}
if (amount < 0)
{
thrownew System.ArgumentOutOfRangeException("amount", amount, DebitAmountLessThanZeroMessage);
}
Attualmente, il metodo di test non gestisce tutti i casi che dovrebbe. Se il metodo sottoposto a test, il metodo Debit non è riuscito a generare un ArgumentOutOfRangeException quando il debitAmount è maggiore del saldo (o minore di zero), il metodo di test passerà. Questo scenario non è valido perché si vuole che il metodo di test non riesca se non viene generata alcuna eccezione.
Questo risultato è un bug nel metodo di test. Per risolvere il problema, aggiungere un'asserzione Assert.Fail alla fine del metodo di test per gestire il caso in cui non viene generata alcuna eccezione.
Eseguendo nuovamente il test, si vede che il test ha ora esito negativo se viene rilevata l'eccezione corretta. Il blocco catch intercetta l'eccezione, ma il metodo continua a essere eseguito e ha esito negativo nella nuova asserzione Assert.Fail. Per risolvere questo problema, aggiungere un'istruzione return dopo il StringAssert nel blocco catch. Riesecuzione del test conferma che il problema è stato risolto. La versione finale del Debit_WhenAmountIsMoreThanBalance_ShouldThrowArgumentOutOfRange è simile alla seguente:
I miglioramenti apportati al codice di test hanno portato a metodi di test più affidabili e informativi. Ma soprattutto, hanno migliorato anche il codice sottoposto a test.
Suggerimento
Questa procedura dettagliata usa il framework di unit test Microsoft per il codice gestito.
Test Explorer può anche eseguire i test da framework di unit test di terze parti con adattatori per Test Explorer. Per ulteriori informazioni, consultare i framework di unit test di terze parti Install.
Iniziare a testare le app C# usando gli strumenti di test in Visual Studio. Informazioni su come scrivere test, usare Esplora test, creare gruppi di test e applicare il modello rosso-verde-refactoring per la scrittura del codice.
Informazioni su come creare un progetto di unit test. Il progetto test può essere nella stessa soluzione del codice di produzione o in una soluzione separata.
Usare Visual Studio per definire ed eseguire unit test per mantenere l'integrità del codice e per individuare errori e errori prima che i clienti eseguano l'operazione.
Informazioni su come sviluppare un metodo testato in C# usando Microsoft Test Framework, che è possibile adattare facilmente per altri linguaggi o framework di test, ad esempio NUnit.
Informazioni sui concetti di unit test in C# e .NET tramite un'esperienza interattiva che crea una soluzione di esempio dettagliata usando il test dotnet e MSTest.
Informazioni sui concetti relativi agli unit test in C# e .NET Core tramite un'esperienza interattiva per la creazione passo-passo di una soluzione di esempio con test dotnet e NUnit.
Informazioni su come usare il framework di unit test Microsoft per il codice gestito per configurare un metodo di unit test per recuperare i valori da un'origine dati.