Udostępnij za pośrednictwem


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

Ten samouczek pokazuje, jak zbudować rozwiązanie zawierające projekt testów jednostkowych oraz projekt kodu źródłowego. Aby wykonać czynności opisane w samouczku przy użyciu wstępnie utworzonego rozwiązania, wyświetl lub pobierz przykładowy kod. Aby uzyskać instrukcje dotyczące pobierania, zobacz Przykłady i samouczki.

Tworzenie rozwiązania

W tej sekcji tworzone jest rozwiązanie zawierające projekty źródłowe i testowe. Ukończone rozwiązanie ma następującą strukturę katalogów:

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

Poniższe instrukcje zawierają kroki tworzenia rozwiązania testowego. Zobacz Polecenia służące do tworzenia rozwiązania testowego, aby uzyskać instrukcje dotyczące tworzenia rozwiązania testowego w jednym kroku.

  • Otwórz okno powłoki.

  • Uruchom następujące polecenie:

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

    Polecenie dotnet new sln tworzy nowe rozwiązanie w katalogu unit-testing-using-dotnet-test .

  • Zmień katalog na folder unit-testing-using-dotnet-test .

  • Uruchom następujące polecenie:

    dotnet new classlib -o PrimeService
    

    Polecenie dotnet new classlib tworzy nowy projekt biblioteki klas w folderze PrimeService . Nowa biblioteka klas będzie zawierać kod do przetestowania.

  • Zmień nazwę Class1.cs na PrimeService.cs.

  • Zastąp kod w PrimeService.cs następującym kodem:

    using System;
    
    namespace Prime.Services
    {
        public class PrimeService
        {
            public bool IsPrime(int candidate)
            {
                throw new NotImplementedException("Not implemented.");
            }
        }
    }
    

    Obecnie ten kod zgłasza błąd NotImplementedException, ale w dalszej części samouczka zaimplementujesz metodę .

  • W katalogu unit-testing-using-dotnet-test uruchom następujące polecenie, aby dodać projekt biblioteki klas do rozwiązania:

    dotnet sln add ./PrimeService/PrimeService.csproj
    
  • Utwórz projekt PrimeService.Tests , uruchamiając następujące polecenie:

    dotnet new xunit -o PrimeService.Tests
    

    Poprzednie polecenie tworzy projekt PrimeService.Tests w katalogu PrimeService.Tests . Projekt testowy używa narzędzia xUnit jako biblioteki testowej. Polecenie konfiguruje również moduł uruchamiający testy, dodając następujące <PackageReference />elementy do pliku projektu:

    • Microsoft.NET.Test.Sdk
    • xunit
    • xunit.runner.visualstudio
    • coverlet.collector
  • Dodaj projekt testowy do pliku rozwiązania, uruchamiając następujące polecenie:

    dotnet sln add ./PrimeService.Tests/PrimeService.Tests.csproj
    
  • Dodaj bibliotekę PrimeService klas jako zależność do projektu PrimeService.Tests :

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

Polecenia umożliwiające utworzenie rozwiązania

Ta sekcja zawiera podsumowanie wszystkich poleceń w poprzedniej sekcji. Pomiń tę sekcję, jeśli wykonano kroki opisane w poprzedniej sekcji.

Następujące polecenia umożliwiają utworzenie rozwiązania testowego na maszynie z systemem Windows. W przypadku systemów macOS i Unix zaktualizuj ren polecenie do wersji ren systemu operacyjnego, aby zmienić nazwę pliku:

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

Postępuj zgodnie z instrukcjami dotyczącymi funkcji "Zastąp kod w PrimeService.cs następującym kodem" w poprzedniej sekcji.

Tworzenie testu

Popularnym podejściem w procesie programowania opartego na testach (TDD) jest napisanie (niepowodzenie) testu przed zaimplementowaniem kodu docelowego. W tym samouczku stosowane jest podejście TDD. Metoda IsPrime jest wywoływana, ale nie zaimplementowana. Połączenie testowe IsPrime kończy się niepowodzeniem. W TDD piszesz test, który wiadomo, że nie przejdzie. Następnie zaktualizujesz kod docelowy, aby test przeszedł pozytywnie. Powtarzasz tę metodę, pisząc test, który kończy się niepowodzeniem, a następnie modyfikując kod docelowy, aby przeszedł.

Zaktualizuj projekt PrimeService.Tests :

  • Usuń plik PrimeService.Tests/UnitTest1.cs.

  • Utwórz plik PrimeService.Tests/PrimeService_IsPrimeShould.cs .

  • Zastąp kod w PrimeService_IsPrimeShould.cs następującym kodem:

    using Xunit;
    using Prime.Services;
    
    namespace Prime.UnitTests.Services
    {
        public class PrimeService_IsPrimeShould
        {
            [Fact]
            public void IsPrime_InputIs1_ReturnFalse()
            {
                var primeService = new PrimeService();
                bool result = primeService.IsPrime(1);
    
                Assert.False(result, "1 should not be prime");
            }
        }
    }
    

Atrybut [Fact] deklaruje metodę testową uruchamianą przez moduł uruchamiający testy. W folderze PrimeService.Tests uruchom dotnet test. Polecenie dotnet test kompiluje zarówno projekty, jak i uruchamia testy. Moduł xUnit uruchamiający testy zawiera punkt wejścia programu do ich uruchomienia. dotnet test uruchamia uruchamiacz testów z użyciem projektu testów jednostkowych.

Test kończy się niepowodzeniem, ponieważ IsPrime nie został zaimplementowany. Korzystając z podejścia TDD, napisz tylko wystarczająco dużo kodu, aby ten test przebiegł pomyślnie. Zaktualizuj IsPrime za pomocą następującego kodu:

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

Uruchom dotnet test. Test zakończy się pomyślnie.

Dodawanie kolejnych testów

Dodaj testy liczb pierwszych dla 0 i -1. Możesz skopiować test utworzony w poprzednim kroku i utworzyć kopie następującego kodu w celu przetestowania wartości 0 i -1. Ale nie rób tego, ponieważ jest lepszy sposób.

var primeService = new PrimeService();
bool result = primeService.IsPrime(1);

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

Kopiowanie kodu testowego, gdy zmienia się tylko parametr, prowadzi do duplikowania kodu i rozrostu testów. Następujące atrybuty xUnit umożliwiają pisanie zestawu podobnych testów:

  • [Theory] reprezentuje zestaw testów, które wykonują ten sam kod, ale mają różne argumenty wejściowe.
  • [InlineData] atrybut określa wartości dla tych danych wejściowych.

Zamiast tworzyć nowe testy, zastosuj poprzednie atrybuty xUnit, aby utworzyć jedną teorię. Zastąp następujący kod...

[Fact]
public void IsPrime_InputIs1_ReturnFalse()
{
    var primeService = new PrimeService();
    bool result = primeService.IsPrime(1);

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

... z następującym kodem:

[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");
}

W poprzednim kodzie [Theory] i [InlineData] umożliwiają testowanie wartości mniejszych niż dwa. Dwa to najmniejsza liczba główna.

Dodaj następujący kod po deklaracji klasy i przed atrybutem [Theory] :

private readonly PrimeService _primeService;

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

Uruchom polecenie dotnet test, a dwa testy kończą się niepowodzeniem. Aby wszystkie testy przeszły, zaktualizuj metodę IsPrime przy użyciu następującego kodu:

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

Zgodnie z podejściem TDD dodaj więcej testów zakończonych niepowodzeniem, a następnie zaktualizuj kod docelowy. Zobacz ukończoną wersję testów i pełną implementację biblioteki.

Ukończona IsPrime metoda nie jest wydajnym algorytmem sprawdzania liczb pierwszych.

Dodatkowe zasoby