Freigeben über


Komponententests für F#-Bibliotheken mit dotnet-Test und NUnit

Dieses Tutorial führt Sie interaktiv Schritt für Schritt durch das Erstellen einer Beispielprojektmappe, um die Konzepte von Komponententests zu erlernen. Wenn Sie das Lernprogramm lieber mit einer vorgefertigten Lösung befolgen möchten, können Sie den Beispielcode anzeigen oder herunterladen , bevor Sie beginnen. Downloadanweisungen finden Sie unter Beispiele und Lernprogramme.

In diesem Artikel wird ein .NET Core-Projekt getestet. Wenn Sie ein ASP.NET Core-Projekt testen, finden Sie weitere Informationen unter Integrationstests in ASP.NET Core.

Voraussetzungen

  • .NET 8 SDK oder höhere Versionen.
  • Ein Text-Editor oder Code-Editor Ihrer Wahl.

Erstellen des Quellprojekts

Öffnen eines Shell-Fensters. Erstellen Sie ein Verzeichnis namens Unit-testing-with-fsharp , um die Lösung zu speichern. Führen Sie in diesem neuen Verzeichnis den folgenden Befehl aus, um eine neue Lösungsdatei für die Klassenbibliothek und das Testprojekt zu erstellen:

dotnet new sln

Erstellen Sie als Nächstes ein MathService-Verzeichnis . Die folgende Gliederung zeigt bisher die Verzeichnis- und Dateistruktur:

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

Machen Sie MathService zum aktuellen Verzeichnis, und führen Sie den folgenden Befehl aus, um das Quellprojekt zu erstellen:

dotnet new classlib -lang "F#"

Sie erstellen eine fehlerhafte Implementierung des mathematischen Diensts:

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

Ändern Sie das Verzeichnis wieder in das Verzeichnis unit-testing-with-fsharp. Führen Sie den folgenden Befehl aus, um das Klassenbibliotheksprojekt zur Projektmappe hinzuzufügen:

dotnet sln add .\MathService\MathService.fsproj

Erstellen des Testprojekts

Erstellen Sie als Nächstes das Verzeichnis MathService.Tests . Die folgende Gliederung zeigt die Verzeichnisstruktur:

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

Erstellen Sie das Verzeichnis MathService.Tests als aktuelles Verzeichnis, und erstellen Sie ein neues Projekt mit dem folgenden Befehl:

dotnet new nunit -lang "F#"

Mit diesem Befehl wird ein Testprojekt erstellt, das NUnit als Testframework verwendet. Die generierte Vorlage konfiguriert den Testläufer 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>

Das Testprojekt erfordert andere Pakete zum Erstellen und Ausführen von Komponententests. dotnet new im vorherigen Schritt wurde NUnit und der NUnit-Testadapter hinzugefügt. Fügen Sie nun die MathService Klassenbibliothek als weitere Abhängigkeit zum Projekt hinzu. Verwenden Sie den Befehl dotnet reference add:

dotnet reference add ../MathService/MathService.fsproj

Die ganze Datei finden Sie im Beispielerepository auf GitHub.

Sie haben das folgende endgültige Lösungslayout:

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

Führen Sie den folgenden Befehl im Verzeichnis "unit-testing-with-fsharp " aus:

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

Erstellen des ersten Tests

Du schreibst einen fehlgeschlagenen Test, machst ihn erfolgreich und wiederholst dann den Vorgang. Öffnen Sie UnitTest1.fs , und fügen Sie den folgenden Code hinzu:

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)

Das [<TestFixture>] Attribut gibt eine Klasse an, die Tests enthält. Das [<Test>] Attribut zeigt eine Testmethode an, die vom Testläufer ausgeführt wird. Wechseln Sie in das Verzeichnis "unit-testing-with-fsharp", führen Sie dotnet test aus, um die Tests und die Klassenbibliothek zu erstellen, und führen Sie dann die Tests aus. Der NUnit-Testläufer enthält den Programmeinstiegspunkt, um Ihre Tests auszuführen. dotnet test startet Test Runner mithilfe des von Ihnen erstellten Komponententestprojekts.

Diese zwei Tests geben jeweils den grundlegendsten bestandenen und fehlerhaften Test an. My test bestanden und Fail every time nicht bestanden. Erstellen Sie nun einen Test für die squaresOfOdds Methode. Die squaresOfOdds Methode gibt eine Sequenz der Quadrate aller ungeraden ganzzahligen Werte zurück, die Teil der Eingabesequenz sind. Anstatt alle diese Funktionen gleichzeitig zu schreiben, können Sie iterativ Tests erstellen, die die Funktionalität überprüfen. Damit jeder Test erfolgreich abgeschlossen wird, muss die erforderliche Funktionalität für die Methode erstellt werden.

Der einfachste Test, den Sie schreiben können, besteht darin, mit allen geraden Zahlen aufzurufen squaresOfOdds , wobei das Ergebnis eine leere Sequenz von ganzzahligen Zahlen sein soll. Hier ist dieser 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))

Beachten Sie, dass die expected Sequenz in eine Liste konvertiert wird. Das NUnit-Framework basiert auf vielen standardmäßigen .NET-Typen. Diese Abhängigkeit bedeutet, dass Ihre öffentliche Schnittstelle und die erwarteten Ergebnisse ICollection anstelle von IEnumerable unterstützen.

Wenn Sie den Test ausführen, sehen Sie, dass der Test fehlschlägt. Das liegt daran, dass Sie die Implementierung noch nicht erstellt haben. Erstellen Sie diesen Testdurchlauf, indem Sie den einfachsten Code in der Klasse "Library.fs " in Ihrem MathService-Projekt schreiben, das funktioniert:

let squaresOfOdds xs =
    Seq.empty<int>

Führen Sie im Verzeichnis unit-testing-with-fsharp erneut dotnet test aus. Der Befehl dotnet test führt einen Build für das MathService Projekt und dann für das MathService.Tests Projekt aus. Nachdem beide Projekte erstellt wurden, führt es Ihre Tests aus. Jetzt sind zwei Tests bestanden.

Erfüllen Sie die Anforderungen

Nachdem Sie nun einen Test bestanden haben, ist es an der Zeit, mehr zu schreiben. Der nächste einfache Fall funktioniert mit einer Sequenz, deren einzige ungerade Zahl ist 1. Die Zahl 1 ist einfacher, da das Quadrat von 1 1 ist. Dies ist der nächste 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))

Die dotnet test Ausführung schlägt den neuen Test fehl. Sie müssen die squaresOfOdds Methode aktualisieren, um diesen neuen Test zu behandeln. Sie müssen alle geraden Zahlen aus der Sequenz filtern, um diesen Testdurchlauf durchzuführen. Dazu können Sie eine kleine Filterfunktion schreiben und folgendes verwenden Seq.filter:

let private isOdd x = x % 2 <> 0

let squaresOfOdds xs =
    xs
    |> Seq.filter isOdd

Es gibt einen weiteren Schritt: Quadratieren Sie jede der ungeraden Zahlen. Beginnen Sie mit dem Schreiben eines neuen Tests:

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

Sie können den Test beheben, indem Sie für die gefilterte Sequenz einen Zuordnungsvorgang durchführen, um das Quadrat von jeder ungerade Zahl zu berechnen:

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

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

Sie haben eine kleine Bibliothek und eine Reihe von Unittests für diese Bibliothek erstellt. Sie haben die Lösung so strukturiert, dass das Hinzufügen neuer Pakete und Tests Teil des normalen Workflows ist. Sie konzentrierten sich größtenteils auf die Lösung der Ziele der Anwendung.

Siehe auch