Condividi tramite


Eseguire test unitari delle librerie F# in .NET Core usando dotnet test e xUnit

Questa esercitazione illustra un'esperienza interattiva che crea una soluzione di esempio dettagliata per apprendere i concetti di unit test. Se preferisci seguire il tutorial usando una soluzione predefinita, visualizza o scarica il codice di esempio prima di iniziare. Per istruzioni sul 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.

Creazione del progetto di origine

Aprire una finestra della shell. Creare una directory denominata unit-testing-with-fsharp per contenere la soluzione. All'interno di questa nuova directory eseguire dotnet new sln per creare una nuova soluzione. In questo modo è più semplice gestire sia la libreria di classi che il progetto di unit test. All'interno della directory della soluzione creare una directory MathService . La struttura di directory e file finora è illustrata di seguito:

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

Impostare MathService sulla directory corrente ed eseguire dotnet new classlib -lang "F#" per creare il progetto di origine. Si creerà 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 dotnet sln add .\MathService\MathService.fsproj per aggiungere il progetto di libreria di classi alla soluzione.

Creazione del 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 dotnet new xunit -lang "F#". Verrà creato un progetto di test che usa xUnit come libreria di test. Il modello generato configura il test runner in MathServiceTests.fsproj:

<ItemGroup>
  <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0-preview-20170628-02" />
  <PackageReference Include="xunit" Version="2.2.0" />
  <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
</ItemGroup>

Il progetto di test richiede altri pacchetti per creare ed eseguire unit test. dotnet new nel passaggio precedente è stato aggiunto xUnit e lo strumento di esecuzione xUnit. 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
        MathServiceTests.fsproj

Esegui dotnet sln add .\MathService.Tests\MathService.Tests.fsproj nella directory unit-testing-with-fsharp.

Creazione del primo test

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

[<Fact>]
let ``My test`` () =
    Assert.True(true)

[<Fact>]
let ``Fail every time`` () = Assert.True(false)

L'attributo [<Fact>] indica un metodo di test eseguito dal test runner. Dall'unit-testing-with-fsharp eseguire dotnet test per compilare i test e la libreria di classi e quindi eseguire i test. Lo strumento di test xUnit contiene il punto di ingresso del programma per eseguire i tuoi 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 più basilari che vengono superati e quelli che non vengono 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à. L'esecuzione di ogni passaggio di test implica la creazione della funzionalità necessaria per il metodo .

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

[<Fact>]
let ``Sequence of Evens returns empty collection`` () =
    let expected = Seq.empty<int>
    let actual = MyMath.squaresOfOdds [2; 4; 6; 8; 10]
    Assert.Equal<Collections.Generic.IEnumerable<int>>(expected, actual)

Il tuo test fallisce. L'implementazione non è ancora stata creata. Eseguire questo test scrivendo il codice più semplice nella classe 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, viene eseguito questo singolo test. Passa.

Completamento dei 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:

[<Fact>]
let ``Sequences of Ones and Evens returns Ones`` () =
    let expected = [1; 1; 1; 1]
    let actual = MyMath.squaresOfOdds [2; 1; 4; 1; 6; 1; 8; 1; 10]
    Assert.Equal<Collections.Generic.IEnumerable<int>>(expected, actual)

L'esecuzione di dotnet test esegue i test e mostra che il nuovo test ha esito negativo. Aggiornare ora il squaresOfOdds metodo per gestire questo nuovo test. È possibile 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:

[<Fact>]
let ``SquaresOfOdds works`` () =
    let expected = [1; 9; 25; 49; 81]
    let actual = MyMath.squaresOfOdds [1; 2; 3; 4; 5; 6; 7; 8; 9; 10]
    Assert.Equal(expected, actual)

È possibile correggere il test trasmettendo la sequenza filtrata attraverso un'operazione di mappatura 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