Testowanie jednostkowe języka C# na platformie .NET przy użyciu testu dotnet i narzędzia xUnit
W tym samouczku pokazano, jak utworzyć rozwiązanie zawierające projekt testu jednostkowego i 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."); } } }
Powyższy kod ma następujące działanie:
- NotImplementedException Zgłasza komunikat z komunikatem wskazującym, że nie został zaimplementowany.
- Zostanie zaktualizowany w dalszej części tego samouczka.
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.
- Konfiguruje moduł uruchamiający testy przez dodanie następujących
<PackageReference />
elementów 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 jest używane podejście TDD. Metoda IsPrime
jest wywoływana, ale nie zaimplementowana. Wywołanie testowe kończy się niepowodzeniem IsPrime
. W przypadku TDD test jest napisany, który jest znany jako niepowodzenie. Kod docelowy jest aktualizowany w celu wykonania testu. Powtarzasz to podejście, pisząc test kończący się niepowodzeniem, a następnie aktualizując kod docelowy do przekazania.
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 polecenie dotnet test
. Polecenie dotnet test kompiluje zarówno projekty, jak i uruchamia 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 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 program 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 tylko parametr zmienia się, powoduje duplikowanie kodu i przeloowanie testowe. 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]
włącz testowanie kilku 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 testowania pierwotnego.