Komponententests für C# in .NET Core mit „dotnet test“ und xUnitUnit testing C# in .NET Core using dotnet test and xUnit

In diesem Tutorial wird gezeigt, wie Sie eine Lösung erstellen, die ein Komponententest- und ein Quellcodeprojekt enthält.This tutorial shows how to build a solution containing a unit test project and source code project. Um dem Tutorial mit einer vorkonfigurierten Projektmappe zu folgen, können Sie sich den Beispielcode ansehen oder ihn herunterladen.To follow the tutorial using a pre-built solution, view or download the sample code. Anweisungen zum Herunterladen finden Sie unter Beispiele und Lernprogramme.For download instructions, see Samples and Tutorials.

Erstellen der ProjektmappeCreate the solution

In diesem Abschnitt wird eine Projektmappe erstellt, die das Quell- und Testprojekt enthält.In this section, a solution is created that contains the source and test projects. Die vervollständigte Projektmappe hat die folgende Verzeichnisstruktur:The completed solution has the following directory structure:

/unit-testing-using-dotnet-test
    unit-testing-using-dotnet-test.sln
    /PrimeService
        PrimeService.cs
        PrimeService.csproj
    /PrimeService.Tests
        PrimeService_IsPrimeShould.cs
        PrimeServiceTests.csproj

In den folgenden Anweisungen werden die Schritte zur Erstellung der Testprojektmappe beschrieben.The following instructions provide the steps to create the test solution. Anweisungen zum Erstellen der Testprojektmappe in einem Schritt finden Sie unter Befehle zum Erstellen einer Testprojektmappe.See Commands to create test solution for instructions to create the test solution in one step.

  • Öffnen eines Shell-Fensters.Open a shell window.

  • Führen Sie den folgenden Befehl aus:Run the following command:

    dotnet new sln -o unit-testing-using-dotnet-test
    

    Der Befehl dotnet new sln erstellt im Verzeichnis unit-testing-using-dotnet-test eine neue Projektmappe.The dotnet new sln command creates a new solution in the unit-testing-using-dotnet-test directory.

  • Ändern Sie das Verzeichnis in unit-testing-using-dotnet-test.Change directory to the unit-testing-using-dotnet-test folder.

  • Führen Sie den folgenden Befehl aus:Run the following command:

    dotnet new classlib -o PrimeService
    

    Der Befehl dotnet new classlib erstellt im Ordner PrimeService ein neues Klassenbibliotheksprojekt.The dotnet new classlib command creates a new class library project in the PrimeService folder. Die neue Klassenbibliothek enthält den zu testenden Code.The new class library will contain the code to be tested.

  • Benennen Sie Class1.cs in PrimeService.cs um.Rename Class1.cs to PrimeService.cs.

  • Ersetzen Sie den Code in PrimeService.cs durch folgenden Code:Replace the code in PrimeService.cs with the following code:

    using System;
    
    namespace Prime.Services
    {
        public class PrimeService
        {
            public bool IsPrime(int candidate)
            {
                throw new NotImplementedException("Not implemented.");
            }
        }
    }
    
  • Der vorangehende Code:The preceding code:

    • Löst eine NotImplementedException mit der Meldung aus, dass die Implementierung fehlt.Throws a NotImplementedException with a message indicating it's not implemented.
    • Wird später im Tutorial aktualisiert.Is updated later in the tutorial.
  • Führen Sie im Verzeichnis unit-testing-using-dotnet-test den folgenden Befehl aus, um das Klassenbibliotheksprojekt zur Projektmappe hinzuzufügen:In the unit-testing-using-dotnet-test directory, run the following command to add the class library project to the solution:

    dotnet sln add ./PrimeService/PrimeService.csproj
    
  • Erstellen Sie das Projekt PrimeService.Tests, indem Sie den folgenden Befehl ausführen:Create the PrimeService.Tests project by running the following command:

    dotnet new xunit -o PrimeService.Tests
    
  • Für den obigen Befehl gilt Folgendes:The preceding command:

    • Erstellt das Projekt PrimeService.Tests im Verzeichnis PrimeService.Tests.Creates the PrimeService.Tests project in the PrimeService.Tests directory. Das Testprojekt verwendet xUnit als Testbibliothek.The test project uses xUnit as the test library.
    • Konfiguriert den Test Runner, indem die folgenden <PackageReference />-Elemente zur Projektdatei hinzugefügt werden:Configures the test runner by adding the following <PackageReference />elements to the project file:
      • Microsoft.NET.Test.Sdk"Microsoft.NET.Test.Sdk"
      • xunit"xunit"
      • xunit.runner.visualstudio"xunit.runner.visualstudio"
  • Fügen Sie das Testprojekt zur Projektmappendatei hinzu, indem Sie den folgenden Befehl ausführen:Add the test project to the solution file by running the following command:

    dotnet sln add ./PrimeService.Tests/PrimeService.Tests.csproj
    
  • Fügen Sie die Klassenbibliothek PrimeService dem Projekt PrimeService.Tests als Abhängigkeit hinzu:Add the PrimeService class library as a dependency to the PrimeService.Tests project:

    dotnet add ./PrimeService.Tests/PrimeService.Tests.csproj reference ./PrimeService/PrimeService.csproj  
    

Befehle zum Erstellen der ProjektmappeCommands to create the solution

In diesem Abschnitt sind alle Befehle des vorherigen Abschnitts zusammengefasst.This section summarizes all the commands in the previous section. Überspringen Sie diesen Abschnitt, wenn Sie die Schritte im vorherigen Abschnitt ausgeführt haben.Skip this section if you've completed the steps in the previous section.

Mit den folgenden Befehlen wird die Testprojektmappe auf einem Windows-Computer erstellt.The following commands create the test solution on a windows machine. Ändern Sie unter macOS und UNIX den Befehl ren in die Betriebssystemversion von ren, um eine Datei umzubenennen:For macOS and Unix, update the ren command to the OS version of ren to rename a file:

dotnet new sln -o unit-testing-using-dotnet-test
cd unit-testing-using-dotnet-test
dotnet new classlib -o PrimeService
ren .\PrimeService\Class1.cs PrimeService.cs
dotnet sln add ./PrimeService/PrimeService.csproj
dotnet new xunit -o PrimeService.Tests
dotnet add ./PrimeService.Tests/PrimeService.Tests.csproj reference ./PrimeService/PrimeService.csproj
dotnet sln add ./PrimeService.Tests/PrimeService.Tests.csproj

Befolgen Sie die Anweisungen unter „Ersetzen Sie den Code in PrimeService.cs durch folgenden Code“ im vorherigen Abschnitt.Follow the instructions for "Replace the code in PrimeService.cs with the following code" in the previous section.

Erstellen eines TestsCreate a test

Ein beliebter Ansatz bei der testgesteuerten Entwicklung ist das Schreiben eines Tests vor Implementierung des Zielcodes.A popular approach in test driven development (TDD) is to write a test before implementing the target code. In diesem Tutorial wird der Ansatz der testgesteuerten Entwicklung befolgt.This tutorial uses the TDD approach. Die IsPrime-Methode ist aufrufbar, aber nicht implementiert.The IsPrime method is callable, but not implemented. Ein Testaufruf von IsPrime schlägt fehl.A test call to IsPrime fails. Bei der testgesteuerten Entwicklung wird ein Test geschrieben, der bekanntermaßen fehlschlägt.With TDD, a test is written that is known to fail. Der Zielcode wird aktualisiert, damit der Test bestanden wird.The target code is updated to make the test pass. Sie wiederholen diesen Ansatz kontinuierlich, schreiben einen nicht erfolgreichen Test und aktualisieren dann den Zielcode so, dass er bestanden wird.You keep repeating this approach, writing a failing test and then updating the target code to pass.

Aktualisieren Sie das Projekt PrimeService.Tests:Update the PrimeService.Tests project:

  • Löschen Sie PrimeService.Tests/UnitTest1.cs.Delete PrimeService.Tests/UnitTest1.cs.
  • Erstellen Sie die Datei PrimeService.Tests/PrimeService_IsPrimeShould.cs.Create a PrimeService.Tests/PrimeService_IsPrimeShould.cs file.
  • Ersetzen Sie den Code in PrimeService_IsPrimeShould.cs durch folgenden Code:Replace the code in PrimeService_IsPrimeShould.cs with the following code:
using Xunit;
using Prime.Services;

namespace Prime.UnitTests.Services
{
    public class PrimeService_IsPrimeShould
    {
        private readonly PrimeService _primeService;

        public PrimeService_IsPrimeShould()
        {
            _primeService = new PrimeService();
        }

        [Fact]
        public void IsPrime_InputIs1_ReturnFalse()
        {
            var result = _primeService.IsPrime(1);

            Assert.False(result, "1 should not be prime");
        }
    }
}

Das [Fact]-Attribut deklariert eine Testmethode, die vom Test Runner ausgeführt wird.The [Fact] attribute declares a test method that's run by the test runner. Führen Sie dotnet test im Ordner PrimeService.Tests aus.From the PrimeService.Tests folder, run dotnet test. Der Befehl dotnet test erstellt beide Projekte und führt die Tests aus.The dotnet test command builds both projects and runs the tests. Der Test Runner für xUnit enthält den Programmeinstiegspunkt zum Ausführen der Tests.The xUnit test runner contains the program entry point to run the tests. dotnet test startet den Test Runner mithilfe des Komponententestprojekts.dotnet test starts the test runner using the unit test project.

Der Test schlägt fehl, da IsPrime nicht implementiert wurde.The test fails because IsPrime hasn't been implemented. Schreiben Sie bei Befolgen des Ansatzes zur testgesteuerten Entwicklung nur so viel Code, dass dieser Test bestanden wird.Using the TDD approach, write only enough code so this test passes. Aktualisieren Sie IsPrime mit folgendem Code:Update IsPrime with the following code:

public bool IsPrime(int candidate)
{
    if (candidate == 1)
    {
        return false;
    }
    throw new NotImplementedException("Not fully implemented.");
}

Führen Sie dotnet test aus.Run dotnet test. Der Test wurde erfolgreich ausgeführt.The test passes.

Hinzufügen weiterer TestsAdd more tests

Fügen Sie Primzahlentests für 0 und-1 hinzu.Add prime number tests for 0 and -1. Sie können den vorangehenden Test kopieren und den folgenden Code so ändern, dass 0 und-1 verwendet werden:You could copy the preceding test and change the following code to use 0 and -1:

var result = _primeService.IsPrime(1);

Assert.False(result, "1 should not be prime");

Das Kopieren von Testcode, wenn sich nur ein Parameter ändert, führt zu Codeduplizierung und Testüberfrachtung.Copying test code when only a parameter changes results in code duplication and test bloat. Die folgenden xUnit-Attribute ermöglichen das Schreiben einer Sammlung ähnlicher Tests:The following xUnit attributes enable writing a suite of similar tests:

  • [Theory] repräsentiert eine Reihe von Tests, die zwar denselben Code ausführen, aber unterschiedliche Eingabeargumente verwenden.[Theory] represents a suite of tests that execute the same code but have different input arguments.
  • Das [InlineData]-Attribut gibt Werte für diese Eingaben an.[InlineData] attribute specifies values for those inputs.

Anstatt neue Tests zu erstellen, wenden Sie die vorhergehenden xUnit-Attribute an, um eine einzelne Theorie zu erstellen.Rather than creating new tests, apply the preceding xUnit attributes to create a single theory. Ersetzen Sie den folgenden Code:Replace the following code:

[Fact]
public void IsPrime_InputIs1_ReturnFalse()
{
    var result = _primeService.IsPrime(1);

    Assert.False(result, "1 should not be prime");
}

durch den folgenden Code:with the following code:

[Theory]
[InlineData(-1)]
[InlineData(0)]
[InlineData(1)]
public void IsPrime_ValuesLessThan2_ReturnFalse(int value)
{
    var result = _primeService.IsPrime(value);

    Assert.False(result, $"{value} should not be prime");
}

Im vorangehenden Code ermöglichen [Theory] und [InlineData] das Testen mehrerer Werte, die kleiner als 2 sind.In the preceding code, [Theory] and [InlineData] enable testing several values less than two. 2 ist die kleinste Primzahl.Two is the smallest prime number.

Führen Sie dotnet test aus. Zwei dieser Tests schlagen fehl.Run dotnet test, two of the tests fail. Aktualisieren Sie die IsPrime-Methode mit folgendem Code, damit alle Tests bestanden werden:To make all of the tests pass, update the IsPrime method with the following code:

public bool IsPrime(int candidate)
{
    if (candidate < 2)
    {
        return false;
    }
    throw new NotImplementedException("Not fully implemented.");
}

Fügen Sie unter Befolgen des Ansatzes zur testgesteuerten Entwicklung weitere nicht erfolgreiche Tests hinzu, und aktualisieren Sie anschließend den Zielcode.Following the TDD approach, add more failing tests, then update the target code. Sehen Sie sich die endgültige Version der Tests und die vollständige Implementierung der Bibliothek an.See the finished version of the tests and the complete implementation of the library.

Die vervollständigte IsPrime-Methode ist kein effizienter Algorithmus für den Primzahltest.The completed IsPrime method is not an efficient algorithm for testing primality.

Zusätzliche RessourcenAdditional resources