Enhetstestning av F#-bibliotek i .NET Core med dotnet-test och xUnit
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ärdig 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.
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 dotnet new sln
för att skapa en ny lösning. Det gör det enklare att hantera både klassbiblioteket och enhetstestprojektet.
Skapa en MathService-katalog i lösningskatalogen. Katalogen och filstrukturen hittills visas nedan:
/unit-testing-with-fsharp
unit-testing-with-fsharp.sln
/MathService
Gör MathService till den aktuella katalogen och kör dotnet new classlib -lang "F#"
för att skapa källprojektet. 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 dotnet sln add .\MathService\MathService.fsproj
för att lägga till klassbiblioteksprojektet i lösningen.
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 .dotnet new xunit -lang "F#"
Detta skapar ett testprojekt som använder xUnit som testbibliotek. Den genererade mallen konfigurerar testlöparen i 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>
Testprojektet kräver andra paket för att skapa och köra enhetstester. dotnet new
i föregående steg lade till xUnit och xUnit-löparen. 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
MathServiceTests.fsproj
Kör dotnet sln add .\MathService.Tests\MathService.Tests.fsproj
i katalogen unit-testing-with-fsharp .
Skapa det första testet
Du skriver ett misslyckat test, gör det godkänt och upprepar sedan processen. Öppna Tests.fs och lägg till följande kod:
[<Fact>]
let ``My test`` () =
Assert.True(true)
[<Fact>]
let ``Fail every time`` () = Assert.True(false)
Attributet [<Fact>]
anger en testmetod som körs av testlöparen. Från unit-testing-with-fsharp kör dotnet test
du för att skapa testerna och klassbiblioteket och kör sedan testerna. xUnit-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. Att göra varje testpass innebär att skapa nödvändiga funktioner för metoden.
Det enklaste testet vi 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:
[<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)
Testet misslyckas. Du har inte skapat implementeringen än. Gör det här testet genom att skriva den enklaste koden i klassen MathService
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örs det här enskilda testet. Den passerar.
Uppfylla 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:
[<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)
Körningen dotnet test
kör dina tester och visar att det nya testet misslyckas. squaresOfOdds
Uppdatera nu metoden för att hantera det nya testet. Du filtrerar alla jämna tal ur sekvensen för att göra det här testet godkänt. 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:
[<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)
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 har koncentrerat dig mest på att lösa programmets mål.