Udostępnij za pośrednictwem


Testowanie jednostkowe bibliotek języka F# na platformie .NET Core przy użyciu testu dotnet i narzędzia xUnit

Ten samouczek przeprowadzi Cię przez interaktywne środowisko tworzenia przykładowego rozwiązania krok po kroku, aby poznać pojęcia dotyczące testowania jednostkowego. Jeśli wolisz wykonać czynności opisane w samouczku przy użyciu wstępnie utworzonego rozwiązania, przed rozpoczęciem wyświetl lub pobierz przykładowy kod . Aby uzyskać instrukcje dotyczące pobierania, zobacz Przykłady i samouczki.

Ten artykuł dotyczy testowania projektu platformy .NET Core. Jeśli testujesz projekt ASP.NET Core, zobacz Testy integracji w programie ASP.NET Core.

Tworzenie projektu źródłowego

Otwórz okno powłoki. Utwórz katalog o nazwie unit-testing-with-fsharp w celu przechowywania rozwiązania. W tym nowym katalogu uruchom polecenie dotnet new sln , aby utworzyć nowe rozwiązanie. Ułatwia to zarządzanie zarówno biblioteką klas, jak i projektem testów jednostkowych. W katalogu rozwiązania utwórz katalog MathService . Do tej pory przedstawiono strukturę katalogów i plików:

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

Utwórz aplikację MathService jako bieżący katalog i uruchom polecenie dotnet new classlib -lang "F#" , aby utworzyć projekt źródłowy. Utworzysz nieudaną implementację usługi matematycznej:

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

Zmień katalog z powrotem na katalog unit-testing-with-fsharp . Uruchom polecenie , dotnet sln add .\MathService\MathService.fsproj aby dodać projekt biblioteki klas do rozwiązania.

Tworzenie projektu testowego

Następnie utwórz katalog MathService.Tests . W poniższym konspekcie przedstawiono strukturę katalogów:

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

Utwórz katalog MathService.Tests jako bieżący katalog i utwórz nowy projekt przy użyciu polecenia dotnet new xunit -lang "F#". Spowoduje to utworzenie projektu testowego, który używa narzędzia xUnit jako biblioteki testowej. Wygenerowany szablon konfiguruje moduł uruchamiający testy w pliku 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>

Projekt testowy wymaga innych pakietów do tworzenia i uruchamiania testów jednostkowych. dotnet new w poprzednim kroku dodano element xUnit i moduł uruchamiający xUnit. Teraz dodaj bibliotekę MathService klas jako inną zależność do projektu. dotnet add reference Użyj polecenia :

dotnet add reference ../MathService/MathService.fsproj

Cały plik można zobaczyć w repozytorium przykładów w witrynie GitHub.

Masz następujący końcowy układ rozwiązania:

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

Wykonaj polecenie dotnet sln add .\MathService.Tests\MathService.Tests.fsproj w katalogu unit-testing-with-fsharp .

Tworzenie pierwszego testu

Napisz jeden test zakończony niepowodzeniem, wykonaj go pomyślnie, a następnie powtórz ten proces. Otwórz plik Tests.fs i dodaj następujący kod:

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

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

Atrybut [<Fact>] określa metodę testową uruchamianą przez moduł uruchamiający testy. W module unit-testing-with-fsharp wykonaj polecenie dotnet test , aby skompilować testy i bibliotekę klas, a następnie uruchomić testy. Moduł uruchamiający testy xUnit zawiera punkt wejścia programu w celu uruchomienia testów. dotnet test uruchamia moduł uruchamiający testy przy użyciu utworzonego projektu testów jednostkowych.

Te dwa testy pokazują najbardziej podstawowe testy z przekazywaniem i niepowodzeniem. My test przechodzi i Fail every time kończy się niepowodzeniem. Teraz utwórz test dla squaresOfOdds metody . Metoda squaresOfOdds zwraca sekwencję kwadratów wszystkich nieparzystnych wartości całkowitych, które są częścią sekwencji danych wejściowych. Zamiast próbować napisać wszystkie te funkcje jednocześnie, można iteracyjne tworzyć testy sprawdzające funkcjonalność. Utworzenie każdego testu z powodzeniem oznacza utworzenie niezbędnych funkcji dla metody .

Najprostszym testem, który możemy napisać, jest wywołanie squaresOfOdds ze wszystkimi liczbami parzystymi, gdzie wynikiem powinna być pusta sekwencja liczb całkowitych. Oto ten 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)

Test kończy się niepowodzeniem. Implementacja nie została jeszcze utworzona. Wykonaj ten test, pisząc najprostszy kod w MathService klasie, która działa:

let squaresOfOdds xs =
    Seq.empty<int>

W katalogu unit-testing-with-fsharp ponownie uruchom polecenie dotnet test . Polecenie dotnet test uruchamia kompilację dla MathService projektu, a następnie dla MathService.Tests projektu. Po utworzeniu obu projektów zostanie uruchomiony ten pojedynczy test. Przechodzi.

Spełnianie wymagań

Teraz, gdy wykonano jeden test, nadszedł czas, aby napisać więcej. Następny prosty przypadek działa z sekwencją, której jedyną nieparzystą liczbą jest 1. Liczba 1 jest łatwiejsza, ponieważ kwadrat 1 wynosi 1. Oto następny 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)

dotnet test Wykonanie uruchomi testy i pokazuje, że nowy test kończy się niepowodzeniem. Teraz zaktualizuj metodę squaresOfOdds , aby obsłużyć ten nowy test. Filtrujesz wszystkie liczby parzystowe z sekwencji, aby wykonać ten test. Można to zrobić, pisząc małą funkcję filtru i używając polecenia Seq.filter:

let private isOdd x = x % 2 <> 0

let squaresOfOdds xs =
    xs
    |> Seq.filter isOdd

Jest jeszcze jeden krok, aby przejść: kwadrat każdej z nieparzystnych liczb. Zacznij od napisania nowego testu:

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

Test można naprawić, potokując filtrowaną sekwencję za pomocą operacji mapy w celu obliczenia kwadratu każdej liczby nieparzysta:

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

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

Utworzono małą bibliotekę i zestaw testów jednostkowych dla tej biblioteki. Rozwiązanie zostało ustrukturyzowane tak, aby dodawanie nowych pakietów i testów było częścią normalnego przepływu pracy. Większość czasu i nakładu pracy na rozwiązywaniu celów aplikacji koncentrujesz się przez większość czasu i wysiłku.

Zobacz też