Condividi tramite


Nozioni fondamentali sugli unit test

In questo argomento vengono descritte le nozioni di base di scrittura e avviamento di uno unit test in Esplora Test di Visual Studio .Include le sezioni seguenti:

Unit testing overview

  • Quick starts

The MyBank Solution example

Creating the unit test projects

Writing your tests

Running tests in Test Explorer

  • Running and viewing tests from the Test Explorer toolbar

  • Running tests after every build

  • Filtering and grouping the test list

Debugging unit tests

Additional tools for unit tests

  • Generating application code from tests

  • Generating multiple tests by using data driven test methods

  • Analyzing unit test code coverage

  • Isolating unit test methods with Microsoft Fakes

Panoramica su Unit test

Esplora Test di Visual Studio è progettato per supportare gli sviluppatori e i team che incorporano unit test nelle procedure di sviluppo software.Unit test aiuta ad assicurare la correttezza del programma verificando che il codice dell'applicazione faccia ciò che ci si aspetta.Negli unit test, si analizza la funzionalità del programma per individuare i comportamenti discreti verificabili che è possibile verificare come singole unità.Utilizzare unit testing framework per creare test di tali comportamenti e per segnalare i risultati dei test.

L'esecuzione di unit test ha il suo più grande effetto quando è parte integrante del flusso di lavoro di sviluppo software.Non appena si scrive una funzione o un altro blocco di codice dell'applicazione, creare uno unit test per verificare il comportamento del codice in risposta a standard, limiti e casi di input non corretto, e per verificare che tutte le ipotesi esplicite o implicite effettuate dal codice.In una procedura di sviluppo software nota come test driven development, è possibile creare uno unit test prima di scrivere il codice, pertanto utilizzare unit test sia per documentazione di progettazione e per specifiche funzionali di funzionalità.

Esplora Test fornisce un modo flessibile ed efficace per eseguire gli unit test e visualizzare i risultati in Visual Studio.Visual Studio installa i Framework per unit test Microsoft per codice gestito e codice nativo.Esplora Test può inoltre eseguire unit test framework di terze parti e open source che implementano interfacce aggiuntive di Esplora Test.È possibile aggiungere molti di questi framework con Visual Studio Gestione Estensioni e tramite Visual Studio gallery.Vedere Procedura: installare framework unit test di terze parti

Le visualizzazioni di Test Explorer possono mostrare tutti i test oppure solo i test superati, non superati, non ancora eseguiti, o che sono stati ignorati.È possibile filtrare i test in qualsiasi visualizzazione facendo corrispondere il testo nella casella di ricerca a livello globale oppure selezionando uno dei filtri predefiniti.È possibile eseguire qualunque selezione di test in ogni momento.Quando si utilizza Visual Studio Ultimate, è possibile eseguire test automaticamente dopo ogni compilazione.I risultati di un'esecuzione dei test sono immediatamente evidenti nella barra superati/non superati nella parte superiore della finestra.I dettagli di un risultato del metodo di test sono visualizzati quando si seleziona il test.

Hh694602.collapse_all(it-it,VS.110).gifAvvii rapidi

Per un'introduzione ad unit test che portano direttamente al codice, vedere uno degli argomenti seguenti:

L'esempio della soluzione di MyBank

In questo argomento, si utilizza lo sviluppo di un'applicazione di finzione chiamata MyBank come esempio.Non è necessario il codice per seguire le spiegazioni in questo argomento.I metodi sono scritti in C# e sono presentati tramite l'utilizzo del Microsoft Unit Testing Framework per Codice Gestito. Tuttavia, i concetti sono facilmente trasferiti in altri linguaggi e framework.

Soluzione MyBank

Un primo tentativo di progettazione per l'applicazione MyBank include un componente di account che rappresenta un singolo account e le sue transazioni con la banca, e componente database che rappresenta la funzionalità per raggruppare e gestire i singoli account.

Viene creata una soluzione MyBank che contiene due progetti:

  • Accounts

  • BankDb

Un primo tentativo per progettare il progetto Accounts contiene una classe per le informazioni di base su un account, un'interfaccia che specifica la funzionalità comune di qualsiasi tipo di account, ad esempio il deposito e il ritiro di risorse dall'account, e una classe derivata dall'interfaccia che rappresenta un account in verifica.Iniziamo i progetti Account creando i seguenti file di origine:

  • AccountInfo.cs definisce le informazioni di base di un account.

  • IAccount.cs definisce un'interfaccia standard IAccountper un account, compresi i metodi per depositare e ritirare risorse da un account e recuperare il saldo del conto.

  • CheckingAccount.cs contiene la classe CheckingAccount che implementa l'interfaccia IAccounts per un account in verifica.

Per esperienza è noto che una cosa che un prelievo da un account deve fare è assicurarsi che la quantità prelevata sia inferiore al saldo del conto.Verrà eseguito quindi l'override del metodo IAccount.Withdaw in CheckingAccount con un metodo che consente di verificare tale condizione.Il metodo potrebbe essere simile al seguente:

public void Withdraw(double amount)
{
    if(m_balance >= amount)
    {
        m_balance -= amount;
    }
    else
    {
        throw new ArgumentException(amount, "Withdrawal exceeds balance!")
    }
}

Ora che il codice è scritto è possibile eseguire la fase di testing.

Creare progetti di unit test

Un progetto unit test in genere rispecchia la struttura di un unico progetto di codice.Nell'esempio di MyBank, aggiungere i progetti di due unit test denominati AccountsTests e BankDbTests alla soluzione MyBanks.I nomi di progetto di test sono arbitrari, ma seguire una convenzione di denominazione standard è opportuno.

Per aggiungere un progetto unit test ad una soluzione:

  1. Scegliere dal menu FileNuovo quindi scegliere Progetto (Tastiera CTRL + MAIUSC + N).

  2. Nella finestra di dialogo Nuovo Progetto, espandere il nodo Installato, scegliere il linguaggio che si desidera utilizzare per il progetto di test e quindi scegliere Test.

  3. Per utilizzare uno dei framework di unit test Microsoft, scegliere Progetto unit test dall'elenco di modelli di progetto.Altrimenti, scegliere il modello di progetto del framework di unit test che si desidera utilizzare.Per testare il progetto Accounts dell'esempio, si potrebbe denominare il progetto AccountsTests.

    Nota di avvisoAttenzione

    Non tutti i framework unit test di terze parti e open source rappresentano un modello di progetto di Visual Studio.Consultare il documento del framework per informazioni sulla creazione di un progetto.

  4. Nel progetto unit test, aggiungere un riferimento al progetto di codice sotto test. Nell'esempio citato un riferimento al progetto Account.

    Per creare il riferimento al progetto di codice:

    1. Selezionare il progetto in Esplora soluzioni.

    2. Dal menu Progetto scegliere Aggiungi Riferimento.

    3. Nella finestra di dialogo Gestione riferimenti, aprire il nodo Soluzione e scegliere Progetti.Selezionare il nome del progetto di codice e chiudere la finestra di dialogo.

Ogni progetto unit test contiene classi che rispecchiano i nomi delle classi nel progetto di codice.Nell'esempio, il progetto AccountsTests potrebbe contenere le seguenti classi:

  • La classe AccountInfoTests contiene i metodi unit test per la classe AccountInfo nel progetto BankAccount

  • La classe CheckingAccountTests contiene i metodi unit test per la classe CheckingAccount.

Scrittura di test

Il framework unit test in uso e Visual Studio IntelliSense guiderà la creazione di unit test per un progetto di codice.Per l'esecuzione in Esplora test, la maggior parte dei framework richiedono di aggiungere gli attributi specifici per identificare i metodi unit test.I framework forniscono inoltre una modalità (in genere con le istruzioni di asserzione o attributi di metodo) per indicare se il metodo test viene superato o non superato.Altri attributi identificano metodi di impostazione opzionali che riferiscono all'inizializzazione della classe e prima che ogni metodo di test e i metodi di smontaggio vengano eseguiti dopo ogni metodo di test e prima che la classe venga eliminata.

Il modello di AAA (Arrange, Act, Assert) è una tecnica comune di scrittura di unit test per un metodo sottoposto a test.

  • La sezione Disponi di un metodo di unit test consente di inizializzare gli oggetti e imposta il valore dei dati passati al metodo sottoposto a test.

  • La sezione Azione richiama il metodo sottoposto a test con parametri disposti.

  • La sezione Asserzione verifica che l'azione del metodo sottoposto a test si comporti come previsto.

Per testare il metodo CheckingAccount.Withdraw dell'esempio, è possibile scrivere due test: uno che verifichi il comportamento standard del metodo e uno che verifichi che un prelievo maggiore del saldo avrà esito negativo.Nella classe CheckingAccountTests si aggiungano i seguenti metodi:

[TestMethod]
public void Withdraw_ValidAmount_ChangesBalance()
{
    // arrange
    double currentBalance = 10.0;
    double withdrawal = 1.0;
    double expected = 9.0;
    var account = new CheckingAccount("JohnDoe", currentBalance);
    // act
    account.Withdraw(withdrawal);
    double actual = account.Balance;
    // assert
    Assert.AreEqual(expected, actual);
}

[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void Withdraw_AmountMoreThanBalance_Throws()
{
    // arrange
    var account = new CheckingAccount("John Doe", 10.0);
    // act
    account.Withdraw(1.0);
    // assert is handled by the ExcpectedException
}

Si noti che Withdraw_ValidAmount_ChangesBalance utilizza un'istruzione esplicita Assert per determinare se il metodo di test ha esito positivo o negativo, mentre Withdraw_AmountMoreThanBalance_Throws utilizza l'attributo ExpectedException per determinare la riuscita del metodo di test.In questo argomento, un framework di unit test esegue il wrapping dei metodi di test in istruzioni di Try/Catch.Nella maggior parte dei casi, se un eccezione viene catturata, il metodo di test ha esito negativo e l'eccezione viene ignorata.L'attributo ExpectedException causa il superamento del test da parte del metodo se l'eccezione specificata viene lanciata.

Per ulteriori informazioni sui Framework Unit Test Microsoft, vedere uno degli argomenti seguenti:

Eseguire i test in Esplora test

Quando si compila il progetto di test, i test vengono visualizzati in Esplora test.Se Esplora test non è visibile, scegliere Test dal menu di Visual Studio, scegliere Windows, quindi scegliere Esplora test.

Esplora unit test

Quando si esegue, si scrive e si riesegue i test, l'aspetto predefinito Esplora test mostra i risultati in gruppi di Test non superati, Test superati, Test ignorati e Test non eseguiti.È possibile scegliere un'intestazione di gruppo per aprire la visualizzazione che mostra tutti i test nel gruppo.

Hh694602.collapse_all(it-it,VS.110).gifEsecuzione e visualizzazione test dalla barra degli strumenti di Esplora test

La barra degli strumenti Esplora test aiuta a trovare,organizzazione ed eseguire i test in questione.

Eseguire test dalla barra degli strumenti di Esplora test

È possibile scegliere Esegui tutto per eseguire tutti i test, oppure scegliere Esegui per selezionare un sottoinsieme dei test da eseguire.Dopo avere eseguito un set di test, un riepilogo dell'esecuzione dei test verrà visualizzato nella parte inferiore della finestra Esplora test.Selezionare un test per visualizzare i dettagli del test nel riquadro inferiore.Scegliere Apri test dal menu di scelta rapida (Tastiera: F12) per visualizzare il codice sorgente per il test selezionato.

Hh694602.collapse_all(it-it,VS.110).gifEsecuzione di test dopo ogni compilazione

Nota di avvisoAttenzione

L'esecuzione di unit test dopo ogni compilazione è supportata solo in Visual Studio Ultimate.

Esecuzione dopo la compilazione

Per eseguire gli unit test dopo ogni compilazione locale, selezionare Test dal menu standard, scegliere Esegui test dopo compilazione nella barra degli strumenti Esplora test.

Hh694602.collapse_all(it-it,VS.110).gifFiltrare e raggruppare l'elenco di test

Quando si dispone di un numero elevato di test, è possibile digitare nella casella di ricerca di Esplora Test per filtrare l'elenco con la stringa specificata.È possibile restringere maggiormente il filtro scegliendo dall'elenco di filtro.

Categorie di filtri di ricerca

Pulsante di raggruppamento di Team Explorer

Per raggruppare i test per categoria, selezionare il pulsante Raggruppa per.

Per ulteriori informazioni, vedere Esecuzione di unit test con Esplora test.

Unit test di debug

È possibile utilizzare Esplora test per avviare una sessione di debug per i test.L'esecuzione passo passo del codice con il debugger di Visual Studio porta in modo semplice avanti e indietro tra unit test e il progetto sottoposto a test.Per avviare il debug:

  1. Nell'editor di Visual Studio, impostare un punto di interruzione in uno o più metodi di test sui quali si desidera eseguire il debug.

    [!NOTA]

    Poiché i metodi di test possono essere eseguiti in qualsiasi ordine, impostare i punti di interruzione in tutti i metodi di test sui quali si desidera eseguire il debug.

  2. In Esplora test, selezionare i metodi di test e quindi scegliere Esegui debug test selezionati dal menu di scelta rapida.

Per ulteriori informazioni riguardo al debugger, vedere Debug in Visual Studio.

Strumenti aggiuntivi per gli unit test

Hh694602.collapse_all(it-it,VS.110).gifGenerazione del codice applicazione dai test

Se si scrivono i test prima di scrivere il codice del progetto, è possibile utilizzare IntelliSense per generare le classi e i metodi nel codice del progetto.Scrivere un'istruzione in un metodo di test che chiama la classe o il metodo che si desidera generare, quindi aprire il menu IntelliSense nella chiamata.Se la chiamata è verso un costruttore di una nuova classe, scegliere dal menu Genera nuovo tipo e seguire la procedura guidata per inserire la classe nel progetto di codice.Se la chiamata è verso un metodo, scegliere Genera nuovo metodo dal menu IntelliSense.

Menu Intellisense Genera stub di metodo

Hh694602.collapse_all(it-it,VS.110).gifGenerazione di multipli test utilizzando i metodi di test basati sui dati

[!NOTA]

Queste procedure si applicano solo ai metodi di test scritti tramite l'unit test framework di Microsoft per il codice gestito.Se si utilizza un framework diverso, consultare la documentazione del framework per funzionalità equivalente.

I metodi di test basati sui dati consentono di verificare un intervallo di valori in un singolo metodo di unit test.Per creare un metodo basato sui dati di unit test, decorare il metodo con un attributo DataSource che specifica l'origine dati e la tabella contenente i valori variabili che si desidera testare.Nel corpo del metodo, assegnare valori di riga alle variabili utilizzando l'indicizzatore TestContext.DataRow[ColumnName].

Ad esempio, ammettiamo di aggiungere un metodo non necessario alla classe CheckingAccount denominata AddIntegerHelper.AddIntegerHelper aggiunge due Integer.

Per creare un test basato sui dati per il metodo AddIntegerHelper, innanzitutto viene creato un database di Access denominato AccountsTest.accdb e una tabella denominata AddIntegerHelperData.La tabella AddIntegerHelperData definisce le colonne per specificare il primo e i secondi operandi dell'addizione e di una colonna per specificare il risultato previsto.Riempiamo una serie di righe di valori appropriati.

    [DataSource(
        @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Projects\MyBank\TestData\AccountsTest.accdb", 
        "AddIntegerHelperData"
    )]
    [TestMethod()]
    public void AddIntegerHelper_DataDrivenValues_AllShouldPass()
    {
        var target = new CheckingAccount();
        int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
        int y = Convert.ToInt32(TestContext.DataRow["SecondNumber"]); 
        int expected = Convert.ToInt32(TestContext.DataRow["Sum"]);
        int actual = target.AddIntegerHelper(x, y);
        Assert.AreEqual(expected, actual);
    }

Il metodo con attributi viene eseguito una volta per ogni riga della tabella.Esplora Test riporta un fallimento del test per il metodo se una qualsiasi delle iterazioni fallisce.Il riquadro dei dettagli dei risultati del test per il metodo mostra lo stato del metodo superato/non superato per ogni riga di dati.

Per ulteriori informazioni, vedere Procedura: creare uno unit test basato sui dati.

Hh694602.collapse_all(it-it,VS.110).gifAnalisi del code coverage di unit test

[!NOTA]

Unit test code coverage è disponibile per linguaggi nativi e gestiti e per tutti i framework di unit test che possono essere eseguiti da Unit Test Framework.

È possibile determinare la quantità di codice del prodotto che effettivamente viene testata dagli unit test utilizzando lo strumento di code coverage di Visual Studio.È possibile eseguire code coverage sui test selezionati o su tutti i test in una soluzione.La finestra Risultati code coverage visualizza la percentuale dei blocchi di codice del prodotto testati per riga, funzione, classe, spazio dei nomi e modulo.

Per eseguire code coverage per i metodi di test in una soluzione,

  1. scegliere test dal menu di Visual Studio e quindi scegliere Analizza code coverage.

  2. Scegliere uno di questi comandi:

    1. Test selezionati esegue i metodi di test selezionati in Esplora Test.

    2. Tutti i test esegue tutti i metodi di test nella soluzione.

I risultati di code coverage vengono visualizzati nella finestra risultati code coverage.

Risultati Code coverage

Per ulteriori informazioni, vedere Utilizzo di code coverage per determinare la quantità di codice testato.

Hh694602.collapse_all(it-it,VS.110).gifIsolamento di metodi di unit test con Microsoft Fakes

[!NOTA]

Microsoft Fakes è disponibile solo in Visual Studio Ultimate.Microsoft Fakes è utilizzabile solamente con i metodi di test scritti usando i framework di unit test per codice gestito.

Il problema

I metodi di unit test incentrati sulla verifica del codice interno di una funzione possono essere difficili da scrivere quando il metodo da testare richiama funzioni che introducono delle dipendenze esterne.Ad esempio, è consigliabile che i metodi della classe di esempio CheckingAccount facciano chiamate al componente BankDb per aggiornare il database principale.È possibile effettuare il refactoring della classe CheckingAccount per ottenere quanto segue:

class CheckingAccount : IAccount
{
    public CheckingAccount(customerName, double startingBalance, IBankDb bankDb)
    {
        m_bankDb = bankDb;
        // set up account
    }

    public void Withdraw(double amount)
    {
        if(m_balance >= amount)
        {
            m_balance = m_MyBankDb.Withdraw(m_accountInfo.ID, amount);
        }
        else
        {
            throw new ArgumentException(amount, "Withdrawal exceeds balance!")
        }
    }

    private IBankDb m_bankDb = null;
    // ...

Gli unit test del metodo CheckingAccount.Withdraw possono ora avere esito negativo a causa dei problemi causati dalla chiamata a m_bankDb.Withdraw.Il database o la connessione di rete possono andare perduti o le autorizzazioni sul database potrebbero essere non adeguate.Un errore nella chiamata m_bankDB.Withdraw causerebbe il fallimento del test per ragioni non correlate al suo codice interno.

La soluzione Microsoft Fakes

Microsoft Fakes crea un assembly contenente le classi e i metodi che è possibile sostituire alle classi nei metodi di unit test che causano le dipendenze.Una classe sostitutiva nel modulo Fakes generato dichiara un metodo e un delegato per ogni metodo pubblico nella parte di destinazione.In un metodo di test, implementare il delegato per creare il comportamento esatto della chiamata della dipendenza nel metodo che si desidera testare.

Nell'esempio, è possibile creare un Fakes assembly per il progetto BankDb e quindi utilizzare la classe StubIBankDb generata da Fakes e che deriva dall'interfaccia IBankDb per rimuovere l'incertezza causata dalle interazioni con il database.Una versione modifed del metodo di test Withdraw_ValidAmount_ChangesBalance sarà simile alla seguente:

[TestMethod]
public void Withdraw_ValidAmount_ChangesBalance()
{
    // arrange
    double currentBalance = 10.0;
    double withdrawal = 1.0;
    double expected = 9.0;

    // set up the Fakes object and delegate
    var stubBankDb = new MyBank.Stubs.StubIBankDb();
    stubBankDb.WithdrawDoubleDouble = (id, amount) => { return 9.0; }
    var account = new CheckingAccount("JohnDoe", currentBalance, stubBankDb);

    // act
    account.Withdraw(withdrawal);
    double actual = account.Balance;

    // assert
    Assert.AreEqual(expected, actual);
}

Questa riga nel metodo di test:

stubBankDb.WithdrawDoubleDouble = (id, amount) => { return 9.0; }

implementa il delegato Fakes per il metodo Withdraw utilizzando una lambda espressione.Il metodo stubBankDb.Withdraw richiama il delegato e quindi restituisce sempre la quantità specificata, che consente al metodo di test in modo affidabile di verificare il comportamento del metodo Accounts.

Ulteriori informazioni su Microsoft Fakes

Microsoft Fakes utilizza due approcci per creare classi sostitutive:

  1. Stub generano le classi sostitutive derivate dall'interfaccia padre della classe dipendenza di destinazione.I metodi stub possono essere sostituiti con metodi virtuali pubblici della classe di destinazione.

  2. Shims usano strumenti runtime per deviare chiamate ad un metodo di destinazione verso un metodo sostitutivo shim per i metodi non virtuali.

In entrambi gli approcci, è possibile usare i delegati generati di chiamate al metodo di dipendenza per specificare il comportamento desiderato nel metodo di test.

Per ulteriori informazioni, vedere Isolamento del codice sottoposto a test con Microsoft Fakes.