Tworzenie testu jednostkowego opartego na danych
Możesz użyć struktury testów jednostkowych firmy Microsoft (MSTest) dla kodu zarządzanego, aby skonfigurować metodę testu jednostkowego w celu pobrania wartości ze źródła danych. Metoda jest uruchamiana kolejno dla każdego wiersza w źródle danych, co ułatwia testowanie różnych danych wejściowych przy użyciu jednej metody.
Test jednostkowy oparty na danych może używać dowolnego z następujących typów:
- dane inline z użyciem atrybutu
DataRow
- dane członkowskie przy użyciu atrybutu
DynamicData
- od znanego dostawcy źródła przy użyciu atrybutu
DataSource
Metoda testowa
Załóżmy na przykład, że masz:
Rozwiązanie o nazwie
MyBank
, które akceptuje i przetwarza transakcje dla różnych typów kont.Projekt w
MyBank
nazywanyBankDb
, który zarządza transakcjami dla kont.Klasa o nazwie
Maths
w projekcieBankDb
, który wykonuje funkcje matematyczne, aby upewnić się, że każda transakcja jest korzystna dla banku.Projekt testu jednostkowego o nazwie
BankDbTests
do testowania zachowania składnikaBankDb
.Klasa testu jednostkowego o nazwie
MathsTests
w celu zweryfikowania zachowania klasyMaths
.
Przetestujemy metodę w Maths
, która dodaje dwie liczby całkowite przy użyciu pętli:
public int AddIntegers(int first, int second)
{
int sum = first;
for (int i = 0; i < second; i++)
{
sum += 1;
}
return sum;
}
Metoda testowa
Wbudowany test oparty na danych
W przypadku testów wbudowanych narzędzie MSTest używa DataRow
do określania wartości używanych przez test oparty na danych. Test w tym przykładzie jest uruchamiany kolejno dla każdego wiersza danych.
[TestMethod]
[DataRow(1, 1, 2)]
[DataRow(2, 2, 4)]
[DataRow(3, 3, 6)]
[DataRow(0, 0, 1)] // The test run with this row fails
public void AddIntegers_FromDataRowTest(int x, int y, int expected)
{
var target = new Maths();
int actual = target.AddIntegers(x, y);
Assert.AreEqual(expected, actual,
"x:<{0}> y:<{1}>",
new object[] {x, y});
}
Test oparty na danych członków
Narzędzie MSTest używa atrybutu DynamicData
do określenia nazwy, rodzaju oraz typu definiującego (domyślnie używany jest bieżący typ) elementu, który dostarczy dane używane przez test oparty na danych.
Notatka
Przed MSTest 3.8 wyliczenie DynamicDataSourceType
miało dwóch członków, Property
i Method
. Wartość domyślna to Property
. Począwszy od MSTest 3.8, nowy element członkowski AutoDetect
jest dodawany do wyliczenia i jest domyślny. Dlatego nie trzeba już określać DynamicDataSourceType
.
public static IEnumerable<object[]> AdditionData
{
get
{
return new[]
{
new object[] { 1, 1, 2 },
new object[] { 2, 2, 4 },
new object[] { 3, 3, 6 },
new object[] { 0, 0, 1 }, // The test run with this row fails
};
}
}
[TestMethod]
[DynamicData(nameof(AdditionData))]
public void AddIntegers_FromDynamicDataTest(int x, int y, int expected)
{
var target = new Maths();
int actual = target.AddIntegers(x, y);
Assert.AreEqual(expected, actual,
"x:<{0}> y:<{1}>",
new object[] {x, y});
}
Możliwe jest również zastąpienie domyślnej wygenerowanej nazwy wyświetlanej poprzez użycie właściwości DynamicDataDisplayName
atrybutu DynamicData
. Sygnatura metody nazwy wyświetlanej musi być public static string
i zaakceptować dwa parametry, pierwszy typu MethodInfo
i drugi typu object[]
.
public static string GetCustomDynamicDataDisplayName(MethodInfo methodInfo, object[] data)
{
return string.Format("DynamicDataTestMethod {0} with {1} parameters", methodInfo.Name, data.Length);
}
[DynamicData(nameof(AdditionData), DynamicDataDisplayName = nameof(GetCustomDynamicDataDisplayName))]
Test oparty na danych dostawcy usług
Tworzenie testu jednostkowego opartego na źródle danych obejmuje następujące kroki:
Utwórz źródło danych zawierające wartości używane w metodzie testowej. Źródło danych może być dowolnym typem zarejestrowanym na maszynie, na której jest uruchamiany test.
Dodaj publiczną właściwość
TestContext
typu TestContext do klasy testowej.Tworzenie metody testu jednostkowego
Dodaj do niego atrybut DataSourceAttribute.
Użyj właściwości indeksatora DataRow, aby pobrać wartości używane w teście.
Tworzenie źródła danych
Aby przetestować metodę AddIntegers
, utwórz źródło danych określające zakres wartości parametrów i oczekiwaną sumę. W tym przykładzie utworzymy bazę danych Sql Compact o nazwie MathsData
i tabelę o nazwie AddIntegersData
zawierającą następujące nazwy i wartości kolumn
Numer pierwszy | SecondNumber | Suma |
---|---|---|
0 | 1 | 1 |
1 | 1 | 2 |
2 | -3 | -1 |
Dodawanie obiektu TestContext do klasy testowej
Struktura testów jednostkowych tworzy obiekt TestContext
do przechowywania informacji o źródle danych na potrzeby testu opartego na danych. Następnie platforma ustawia ten obiekt jako wartość tworzonej właściwości TestContext
.
public TestContext TestContext { get; set; }
W metodzie testowej uzyskujesz dostęp do danych za pośrednictwem właściwości indeksatora DataRow
TestContext
.
Notatka
Platforma .NET Core nie obsługuje atrybutu DataSource. Jeśli spróbujesz uzyskać dostęp do danych testowych w ten sposób w projekcie testów jednostkowych platformy .NET Core, platformy UWP lub WinUI, zostanie wyświetlony błąd podobny do "TestContext" nie zawiera definicji elementu "DataRow" i nie można odnaleźć dostępnej metody rozszerzenia "DataRow" akceptującej pierwszy argument typu "TestContext" (czy brakuje dyrektywy using lub odwołania do zestawu?)".
Pisanie metody testowej
Metoda testowa dla AddIntegers
jest dość prosta. Dla każdego wiersza w źródle danych wywołaj AddIntegers
z wartościami kolumn FirstNumber i SecondNumber jako parametrami, a następnie sprawdź, czy wartość zwrócona zgadza się z wartością w kolumnie Sum.
[TestMethod]
[DataSource(@"Provider=Microsoft.SqlServerCe.Client.4.0; Data Source=C:\Data\MathsData.sdf;", "Numbers")]
public void AddIntegers_FromDataSourceTest()
{
var target = new Maths();
// Access the data
int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
int y = Convert.ToInt32(TestContext.DataRow["SecondNumber"]);
int expected = Convert.ToInt32(TestContext.DataRow["Sum"]);
int actual = target.AddIntegers(x, y);
Assert.AreEqual(expected, actual,
"x:<{0}> y:<{1}>",
new object[] {x, y});
}
Określanie elementu DataSourceAttribute
Atrybut DataSource
określa parametry połączenia dla źródła danych i nazwę tabeli używanej w metodzie testowej. Dokładne informacje w parametrach połączenia różnią się w zależności od rodzaju używanego źródła danych. W tym przykładzie użyliśmy bazy danych SqlServerCe.
[DataSource(@"Provider=Microsoft.SqlServerCe.Client.4.0;Data Source=C:\Data\MathsData.sdf", "AddIntegersData")]
Ostrożność
Parametry połączenia mogą zawierać poufne dane (na przykład hasło). Parametry połączenia są przechowywane w postaci zwykłego tekstu w kodzie źródłowym i w skompilowanym zestawie. Ogranicz dostęp do kodu źródłowego i zestawu, aby chronić te poufne informacje.
Atrybut DataSource ma trzy konstruktory.
[DataSource(dataSourceSettingName)]
Konstruktor z jednym parametrem używa informacji o połączeniu przechowywanych w pliku app.config dla rozwiązania. dataSourceSettingsName jest nazwą elementu Xml w pliku konfiguracji, który określa informacje o połączeniu.
Użycie pliku app.config umożliwia zmianę lokalizacji źródła danych bez wprowadzania zmian w samym teście jednostkowym. Aby uzyskać informacje o sposobie tworzenia i używania pliku app.config, zobacz przewodnik : Używanie pliku konfiguracji do definiowania źródła danych
[DataSource(connectionString, tableName)]
Konstruktor DataSource
z dwoma parametrami określa parametry połączenia dla źródła danych i nazwę tabeli zawierającej dane dla metody testowej.
Parametry połączenia zależą od typu źródła danych, ale powinny zawierać element Dostawcy, który określa niezmienną nazwę dostawcy danych.
[DataSource(
dataProvider,
connectionString,
tableName,
dataAccessMethod
)]
Uzyskiwanie dostępu do danych przy użyciu pliku TestContext.DataRow
Aby uzyskać dostęp do danych w tabeli AddIntegersData
, użyj indeksatora TestContext.DataRow
.
DataRow
jest obiektem DataRow, więc pobieraj wartości kolumn według nazw indeksów lub kolumn. Ponieważ wartości są zwracane jako obiekty, przekonwertuj je na odpowiedni typ:
int x = Convert.ToInt32(TestContext.DataRow["FirstNumber"]);
Uruchamianie testu i wyświetlanie wyników
Po zakończeniu pisania metody testowej skompiluj projekt testowy. Metoda testowa jest wyświetlana w eksploratorze testów w grupie Nie uruchamiaj testów. Podczas uruchamiania, zapisywania i ponownego uruchamiania testów Eksplorator testów wyświetla wyniki w grupach Nieudane testy, Zaliczone testyi Nieuruchomione testy. Możesz wybrać Uruchom wszystkie, aby uruchomić wszystkie testy, lub wybrać Uruchom, aby wybrać podzbiór testów do uruchomienia.
Podczas wykonywania testu, animowany pasek wyników testu znajduje się na górze Eksploratora Testów. Na końcu przebiegu testu pasek będzie zielony, jeśli wszystkie testy przeszły lub czerwony, jeśli którykolwiek z testów zakończył się niepowodzeniem. Podsumowanie przebiegu testu jest wyświetlane w okienku szczegółów w dolnej części okna Eksploratora testów. Wybierz test, aby wyświetlić szczegóły tego testu w dolnym okienku.
Notatka
Istnieje wynik dla każdego wiersza danych, a także jeden wynik podsumowania. Jeśli test przebiegł pomyślnie dla każdego wiersza danych, przebieg podsumowania jest wyświetlany jako Passed. Jeśli test zakończył się niepowodzeniem w dowolnym wierszu danych, przebieg podsumowania jest wyświetlany jako Niepowodzenie.
Jeśli w naszym przykładzie uruchomiono dowolną metodę AddIntegers_FromDataRowTest
, AddIntegers_FromDynamicDataTest
lub AddIntegers_FromDataSourceTest
, pasek wyników zmienia kolor na czerwony, a metoda testowa zostaje przeniesiona do Nieudane Testy. Test oparty na danych kończy się niepowodzeniem, jeśli którakolwiek z iterowanych metod ze źródła danych zakończy się niepowodzeniem. Po wybraniu testu opartego na danych, który zakończył się niepowodzeniem w oknie Eksploratora testów, w okienku szczegółów zostaną wyświetlone wyniki każdej iteracji identyfikowanej przez indeks wiersza danych. W naszym przykładzie wydaje się, że algorytm AddIntegers
nie obsługuje poprawnie wartości ujemnych.
Po skorygowaniu metody w ramach testu i ponownym uruchomieniu testu pasek wyników zmieni kolor na zielony, a metoda testowa zostanie przeniesiona do grupy Test z powodzeniem.
Powiązana zawartość
- Microsoft.VisualStudio.TestTools.UnitTesting.DataSourceAttribute
- Microsoft.VisualStudio.TestTools.UnitTesting.TestContext
- Microsoft.VisualStudio.TestTools.UnitTesting.TestContext.DataRow
- Microsoft.VisualStudio.TestTools.UnitTesting.Assert
- Przeprowadzaj testy jednostkowe dla swojego kodu
- Uruchamianie testów jednostkowych za pomocą eksploratora testów
- Pisanie testów jednostkowych dla platformy .NET przy użyciu platformy testów jednostkowych firmy Microsoft