Dela via


Enhetstestning av F#-bibliotek med dotnet-test och NUnit

I den här självstudien får du en interaktiv upplevelse när du skapar en exempellösning steg för steg för att lära dig enhetstestningskoncept. Om du föredrar att följa självstudien med hjälp av en fördefinierad lösning kan du visa eller ladda ned exempelkoden innan du börjar. Instruktioner för nedladdning finns i Exempel och självstudier.

Den här artikeln handlar om att testa ett .NET Core-projekt. Om du testar ett ASP.NET Core-projekt kan du läsa Integreringstester i ASP.NET Core.

Förutsättningar

  • .NET 8 SDK eller senare versioner.
  • Valfri textredigerare eller kodredigerare.

Skapa källprojektet

Öppna ett gränssnittsfönster. Skapa en katalog med namnet unit-testing-with-fsharp för att lagra lösningen. I den här nya katalogen kör du följande kommando för att skapa en ny lösningsfil för klassbiblioteket och testprojektet:

dotnet new sln

Skapa sedan en MathService-katalog . Följande disposition visar katalogen och filstrukturen hittills:

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

Gör MathService till den aktuella katalogen och kör följande kommando för att skapa källprojektet:

dotnet new classlib -lang "F#"

Du skapar en misslyckad implementering av matematiktjänsten:

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

Ändra tillbaka katalogen till katalogen unit-testing-with-fsharp . Kör följande kommando för att lägga till klassbiblioteksprojektet i lösningen:

dotnet sln add .\MathService\MathService.fsproj

Skapa testprojektet

Skapa sedan katalogen MathService.Tests . Följande disposition visar katalogstrukturen:

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

Gör katalogen MathService.Tests till den aktuella katalogen och skapa ett nytt projekt med hjälp av följande kommando:

dotnet new nunit -lang "F#"

Det här kommandot skapar ett testprojekt som använder NUnit som testramverk. Den genererade mallen konfigurerar testlöparen i 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>

Testprojektet kräver andra paket för att skapa och köra enhetstester. dotnet new I föregående steg lades NUnit och NUnit-testkortet till. Lägg nu till MathService klassbiblioteket som ett annat beroende till projektet. dotnet add reference Använd kommandot:

dotnet add reference ../MathService/MathService.fsproj

Du kan se hela filen i exempellagringsplatsen på GitHub.

Du har följande slutgiltiga lösningslayout:

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

Kör följande kommando i katalogen unit-testing-with-fsharp :

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

Skapa det första testet

Du skriver ett misslyckat test, gör det godkänt och upprepar sedan processen. Öppna UnitTest1.fs och lägg till följande kod:

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)

Attributet [<TestFixture>] anger en klass som innehåller tester. Attributet [<Test>] anger en testmetod som körs av testlöparen. Från katalogen unit-testing-with-fsharp kör dotnet test du för att skapa testerna och klassbiblioteket och kör sedan testerna. NUnit-testlöparen innehåller programmets startpunkt för att köra dina tester. dotnet test startar testkören med det enhetstestprojekt som du har skapat.

De här två testerna visar de mest grundläggande testerna för att klara och misslyckas. My test passerar och Fail every time misslyckas. Skapa nu ett test för squaresOfOdds metoden. Metoden squaresOfOdds returnerar en sekvens av kvadraterna för alla udda heltalsvärden som ingår i indatasekvensen. I stället för att försöka skriva alla dessa funktioner samtidigt kan du iterativt skapa tester som validerar funktionerna. Om du vill göra varje testpass innebär det att du skapar de nödvändiga funktionerna för metoden.

Det enklaste testet du kan skriva är att anropa squaresOfOdds med alla jämna tal, där resultatet ska vara en tom sekvens med heltal. Här är testet:

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

Observera att sekvensen expected konverteras till en lista. NUnit-ramverket förlitar sig på många standardtyper av .NET. Det beroendet innebär att ditt offentliga gränssnitt och förväntade resultat stöder ICollection i stället IEnumerableför .

När du kör testet ser du att testet misslyckas. Det beror på att du inte har skapat implementeringen än. Gör det här testet genom att skriva den enklaste koden i klassen Library.fs i ditt MathService-projekt som fungerar:

let squaresOfOdds xs =
    Seq.empty<int>

Kör igen i katalogen dotnet test unit-testing-with-fsharp. Kommandot dotnet test kör en version för MathService projektet och sedan för MathService.Tests projektet. När du har skapat båda projekten kör den dina tester. Två tester godkänns nu.

Slutför kraven

Nu när du har gjort ett testpass är det dags att skriva mer. Nästa enkla fall fungerar med en sekvens vars enda udda tal är 1. Talet 1 är enklare eftersom kvadraten 1 är 1. Här är nästa test:

[<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))

dotnet test Körningen misslyckas med det nya testet. Du måste uppdatera squaresOfOdds metoden för att hantera det nya testet. Du måste filtrera bort alla jämna tal från sekvensen för att det här testet ska gå igenom. Du kan göra det genom att skriva en liten filterfunktion och använda Seq.filter:

let private isOdd x = x % 2 <> 0

let squaresOfOdds xs =
    xs
    |> Seq.filter isOdd

Det finns ytterligare ett steg att gå: kvadrat var och en av de udda talen. Börja med att skriva ett nytt 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))

Du kan åtgärda testet genom att skicka den filtrerade sekvensen via en kartåtgärd för att beräkna kvadraten för varje udda tal:

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

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

Du har skapat ett litet bibliotek och en uppsättning enhetstester för biblioteket. Du har strukturerat lösningen så att tillägg av nya paket och tester är en del av det normala arbetsflödet. Du koncentrerade dig mest på att lösa programmets mål.

Se även