Testing unità di librerie .NET Core di Visual Basic usando il test dotnet e MSTest

In questa esercitazione viene illustrata un'esperienza interattiva di compilazione passo passo di una soluzione di esempio finalizzata all'apprendimento dei concetti base del testing unità. Se si preferisce seguire l'esercitazione usando una soluzione preesistente, visualizzare o scaricare il codice di esempio prima di iniziare. Per istruzioni sul download, vedere Esempi ed esercitazioni.

Questo articolo è relativo al test di un progetto .NET Core. Se si sta testando un progetto ASP.NET Core, vedere Test di integrazione in ASP.NET Core.

Creazione del progetto di origine

Aprire una finestra della shell. Creare una directory denominata unit-testing-vb-mstest in cui archiviare la soluzione. In questa nuova directory eseguire dotnet new sln per creare una nuova soluzione. Questa procedura semplifica la gestione sia della libreria di classi che del progetto di unit test. All'interno della directory della soluzione creare una directory PrimeService. Finora è stata creata la struttura di directory e file seguente:

/unit-testing-vb-mstest
    unit-testing-vb-mstest.sln
    /PrimeService

Impostare PrimeService come directory corrente ed eseguire dotnet new classlib -lang VB per creare il progetto di origine. Rinominare Class1.VB in PrimeService.VB. Si crea un'implementazione non corretta della classe PrimeService:

Namespace Prime.Services
    Public Class PrimeService
        Public Function IsPrime(candidate As Integer) As Boolean
            Throw New NotImplementedException("Please create a test first")
        End Function
    End Class
End Namespace

Tornare alla directory unit-testing-vb-using-mstest. Eseguire dotnet sln add .\PrimeService\PrimeService.vbproj per aggiungere il progetto di libreria di classi alla soluzione.

Creazione del progetto di test

Creare quindi la directory PrimeService.Tests. Di seguito è illustrata la struttura di directory:

/unit-testing-vb-mstest
    unit-testing-vb-mstest.sln
    /PrimeService
        Source Files
        PrimeService.vbproj
    /PrimeService.Tests

Impostare PrimeService.Tests come directory corrente e creare un nuovo progetto usando dotnet new mstest -lang VB. Questo comando crea un progetto di test che usa MSTest come libreria di test. Il modello generato configura il Test Runner nel file PrimeServiceTests.vbproj:

<ItemGroup>
  <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.5.0" />
  <PackageReference Include="MSTest.TestAdapter" Version="1.1.18" />
  <PackageReference Include="MSTest.TestFramework" Version="1.1.18" />
</ItemGroup>

Per creare ed eseguire unit test, il progetto di test richiede altri pacchetti. Nel passaggio precedente dotnet new ha aggiunto MSTest e il Runner di MSTest. Aggiungere ora la libreria di classi PrimeService come un'altra dipendenza del progetto. Usare il comando dotnet add reference:

dotnet add reference ../PrimeService/PrimeService.vbproj

È possibile visualizzare l'intero file nel repository degli esempi su GitHub.

Il layout della soluzione finale è il seguente:

/unit-testing-vb-mstest
    unit-testing-vb-mstest.sln
    /PrimeService
        Source Files
        PrimeService.vbproj
    /PrimeService.Tests
        Test Source Files
        PrimeServiceTests.vbproj

Eseguire dotnet sln add .\PrimeService.Tests\PrimeService.Tests.vbproj nella directory unit-testing-vb-mstest.

Creazione del primo test

Scrivere un test che genera errore, fare in modo che venga superato e quindi ripetere il processo. Rimuovere UnitTest1.vb dalla directory PrimeService.Tests e creare un nuovo file di Visual Basic denominato PrimeService_IsPrimeShould.VB. Aggiungere il codice seguente:

Imports Microsoft.VisualStudio.TestTools.UnitTesting

Namespace PrimeService.Tests
    <TestClass>
    Public Class PrimeService_IsPrimeShould
        Private _primeService As Prime.Services.PrimeService = New Prime.Services.PrimeService()

        <TestMethod>
        Sub IsPrime_InputIs1_ReturnFalse()
            Dim result As Boolean = _primeService.IsPrime(1)

            Assert.IsFalse(result, "1 should not be prime")
        End Sub

    End Class
End Namespace

L'attributo <TestClass> indica una classe che contiene test. L'attributo <TestMethod> indica un metodo eseguito dal Test Runner. Da unit-testing-vb-mstest eseguire dotnet test per compilare i test e la libreria di classi, quindi eseguire i test. Il Test Runner di MSTest include il punto d'ingresso del programma per l'esecuzione dei test. dotnet test avvia il Test Runner usando il progetto di unit test creato.

Il test ha esito negativo. Non è stata ancora creata l'implementazione. Fare in modo che questo test venga superato scrivendo il codice più semplice e funzionante nella classe PrimeService:

Public Function IsPrime(candidate As Integer) As Boolean
    If candidate = 1 Then
        Return False
    End If
    Throw New NotImplementedException("Please create a test first.")
End Function

Eseguire di nuovo dotnet test nella directory unit-testing-vb-mstest. Il comando dotnet test esegue prima una compilazione del progetto PrimeService e quindi del progetto PrimeService.Tests. Dopo la compilazione di entrambi i progetti, verrà eseguito il test singolo, che viene superato.

Aggiunta di altre funzionalità

Ora che il test è stato superato, è necessario scriverne altri. Esistono alcuni altri casi semplici per i numeri primi: 0, -1. È possibile aggiungerli come nuovi test, con l'attributo <TestMethod>, ma questa operazione risulta rapidamente noiosa. Sono disponibili altri attributi di MSTest che consentono di scrivere una suite di test analoghi. Un attributo <DataTestMethod> rappresenta una suite di test che eseguono lo stesso codice, ma hanno argomenti di input diversi. È possibile usare l'attributo <DataRow> per specificare i valori per tali input.

Anziché creare nuovi test, applicare questi due attributi per creare una singola teoria. La teoria è un metodo che verifica vari valori minori di due, ovvero il numero primo più piccolo:

<TestClass>
Public Class PrimeService_IsPrimeShould
    Private _primeService As Prime.Services.PrimeService = New Prime.Services.PrimeService()

    <DataTestMethod>
    <DataRow(-1)>
    <DataRow(0)>
    <DataRow(1)>
    Sub IsPrime_ValuesLessThan2_ReturnFalse(value As Integer)
        Dim result As Boolean = _primeService.IsPrime(value)

        Assert.IsFalse(result, $"{value} should not be prime")
    End Sub

    <DataTestMethod>
    <DataRow(2)>
    <DataRow(3)>
    <DataRow(5)>
    <DataRow(7)>
    Public Sub IsPrime_PrimesLessThan10_ReturnTrue(value As Integer)
        Dim result As Boolean = _primeService.IsPrime(value)

        Assert.IsTrue(result, $"{value} should be prime")
    End Sub

    <DataTestMethod>
    <DataRow(4)>
    <DataRow(6)>
    <DataRow(8)>
    <DataRow(9)>
    Public Sub IsPrime_NonPrimesLessThan10_ReturnFalse(value As Integer)
        Dim result As Boolean = _primeService.IsPrime(value)

        Assert.IsFalse(result, $"{value} should not be prime")
    End Sub
End Class

Eseguire dotnet test. Due test hanno esito negativo. Per assicurare che tutti i test vengano superati, modificare la clausola if all'inizio del metodo:

if candidate < 2

Continuare a eseguire l'iterazione aggiungendo altri test, altre teorie e altro codice nella libreria principale. Si ottiene la versione completa dei test e l'implementazione completa della libreria.

È stata compilata una piccola libreria e un set di unit test per tale libreria. La soluzione è stata strutturata in modo che l'aggiunta di nuovi pacchetti e test faccia parte del normale flusso di lavoro. La maggior parte del tempo e dell'impegno è dedicata alla soluzione degli obiettivi dell'applicazione.