Condividi tramite


Test unitari delle librerie F# utilizzando dotnet test e NUnit

Questa esercitazione illustra un'esperienza interattiva che crea una soluzione di esempio dettagliata per apprendere i concetti di unit test. Se si preferisce seguire l'esercitazione usando una soluzione predefinita, visualizzare o scaricare il codice di esempio prima di iniziare. Per istruzioni di download, vedere Esempi ed esercitazioni.

Questo articolo descrive il test di un progetto .NET Core. Se si sta testando un progetto ASP.NET Core, vedere test di integrazione in ASP.NET Core.

Prerequisiti

  • .NET 8 SDK o versioni successive.
  • Un editor di testo o editor di codice di propria scelta.

Creare il progetto di origine

Aprire una finestra della shell. Creare una directory denominata unit-testing-with-fsharp per contenere la soluzione. In questa nuova directory eseguire il comando seguente per creare un nuovo file di soluzione per la libreria di classi e il progetto di test:

dotnet new sln

Creare quindi una directory MathService . Il seguente schema mostra la struttura di directory e file:

/unit-testing-with-fsharp
    unit-testing-with-fsharp.sln
    /MathService

Impostare MathService sulla directory corrente ed eseguire il comando seguente per creare il progetto di origine:

dotnet new classlib -lang "F#"

Si crea un'implementazione non riuscita del servizio matematico:

module MyMath =
    let squaresOfOdds xs = raise (System.NotImplementedException("You haven't written a test yet!"))

Cambia la directory tornando alla directory unit-testing-with-fsharp. Eseguire il comando seguente per aggiungere il progetto di libreria di classi alla soluzione:

dotnet sln add .\MathService\MathService.fsproj

Creare il progetto di test

Creare quindi la directory MathService.Tests . La seguente illustrazione mostra la struttura della directory:

/unit-testing-with-fsharp
    unit-testing-with-fsharp.sln
    /MathService
        Source Files
        MathService.fsproj
    /MathService.Tests

Impostare la directory MathService.Tests nella directory corrente e creare un nuovo progetto usando il comando seguente:

dotnet new nunit -lang "F#"

Questo comando crea un progetto di test che usa NUnit come framework di test. Il modello generato configura il test runner in MathServiceTests.fsproj:

<ItemGroup>
  <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
  <PackageReference Include="NUnit" Version="4.1.0" />
  <PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
</ItemGroup>

Il progetto di test richiede altri pacchetti per creare ed eseguire unit test. dotnet new nel passaggio precedente sono stati aggiunti NUnit e l'adattatore di test NUnit. Aggiungere ora la libreria di classi MathService come altra dipendenza al progetto. Usare il comando dotnet reference add:

dotnet reference add ../MathService/MathService.fsproj

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

Il layout finale della soluzione è il seguente:

/unit-testing-with-fsharp
    unit-testing-with-fsharp.sln
    /MathService
        Source Files
        MathService.fsproj
    /MathService.Tests
        Test Source Files
        MathService.Tests.fsproj

Eseguire il comando seguente nella directory unit-testing-with-fsharp :

dotnet sln add .\MathService.Tests\MathService.Tests.fsproj

Creare il primo test

Si scrive un test con esito negativo, si passa, quindi si ripete il processo. Aprire UnitTest1.fs e aggiungere il codice seguente:

namespace MathService.Tests

open System
open NUnit.Framework
open MathService

[<TestFixture>]
type TestClass () =

    [<Test>]
    member this.TestMethodPassing() =
        Assert.That(true, Is.True)

    [<Test>]
     member this.FailEveryTime() = Assert.That(false, Is.True)

L'attributo [<TestFixture>] indica una classe che contiene test. L'attributo [<Test>] indica un metodo di test eseguito dal test runner. Dalla directory unit-testing-with-fsharp eseguire dotnet test per compilare i test e la libreria di classi e quindi eseguire i test. Il test runner NUnit contiene il punto di ingresso del programma per eseguire i test. dotnet test avvia lo strumento di esecuzione dei test usando il progetto di test unitario che hai creato.

Questi due test mostrano i test di base superati e non superati. My test passa e Fail every time fallisce. Creare ora un test per il squaresOfOdds metodo . Il squaresOfOdds metodo restituisce una sequenza dei quadrati di tutti i valori interi dispari che fanno parte della sequenza di input. Invece di provare a scrivere tutte queste funzioni contemporaneamente, è possibile creare in modo iterativo test che convalidano la funzionalità. Per garantire che ogni test venga superato, bisogna creare la funzionalità necessaria per il metodo.

Il test più semplice che è possibile scrivere consiste nel chiamare squaresOfOdds con tutti i numeri pari, dove il risultato deve essere una sequenza vuota di numeri interi. Ecco questo test:

[<Test>]
member this.TestEvenSequence() =
    let expected = Seq.empty<int>
    let actual = MyMath.squaresOfOdds [2; 4; 6; 8; 10]
    Assert.That(actual, Is.EqualTo(expected))

Si noti che la expected sequenza viene convertita in un elenco. Il framework NUnit si basa su molti tipi .NET standard. Questa dipendenza significa che l'interfaccia pubblica e i risultati previsti supportano ICollection anziché IEnumerable.

Quando esegui il test, vedrai che il tuo test fallisce. Questo perché non è ancora stata creata l'implementazione. Eseguire questo test scrivendo il codice più semplice nella classe Library.fs nel progetto MathService che funziona:

let squaresOfOdds xs =
    Seq.empty<int>

Nella directory unit-testing-with-fsharp eseguire dotnet test di nuovo. Il comando dotnet test esegue una compilazione per il progetto MathService e quindi per il progetto MathService.Tests. Dopo la compilazione di entrambi i progetti, esegue i tuoi test. Ora due test superati.

Soddisfare i requisiti

Ora che hai superato un test, è il momento di scrivere altri test. Il caso semplice successivo funziona con una sequenza il cui solo numero dispari è 1. Il numero 1 è più facile perché il quadrato di 1 è 1. Ecco il test successivo:

[<Test>]
member public this.TestOnesAndEvens() =
    let expected = [1; 1; 1; 1]
    let actual = MyMath.squaresOfOdds [2; 1; 4; 1; 6; 1; 8; 1; 10]
    Assert.That(actual, Is.EqualTo(expected))

L'esecuzione di dotnet test fallisce il nuovo test. È necessario aggiornare il squaresOfOdds metodo per gestire questo nuovo test. È necessario filtrare tutti i numeri pari fuori dalla sequenza per passare questo test. A tale scopo, scrivere una piccola funzione di filtro e usare Seq.filter:

let private isOdd x = x % 2 <> 0

let squaresOfOdds xs =
    xs
    |> Seq.filter isOdd

C'è un altro passo da fare: quadrare ciascuno dei numeri dispari. Iniziare scrivendo un nuovo test:

[<Test>]
member public this.TestSquaresOfOdds() =
    let expected = [1; 9; 25; 49; 81]
    let actual = MyMath.squaresOfOdds [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
    Assert.That(actual, Is.EqualTo(expected))

È possibile correggere il test eseguendo il piping della sequenza filtrata tramite un'operazione di mapping per calcolare il quadrato di ogni numero dispari:

let private square x = x * x
let private isOdd x = x % 2 <> 0

let squaresOfOdds xs =
    xs
    |> Seq.filter isOdd
    |> Seq.map square

Hai creato una piccola libreria e un set di test unitari 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 dello sforzo è stata concentrata sulla risoluzione degli obiettivi dell'applicazione.

Vedere anche