Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Testování řízené daty umožňuje spustit stejnou testovací metodu s více sadami vstupních dat. Místo psaní samostatných testovacích metod pro každý testovací případ definujte logiku testu jednou a zadejte různé vstupy prostřednictvím atributů nebo externích zdrojů dat.
Přehled
MSTest poskytuje několik atributů pro testování řízené daty:
| Vlastnost | Případ použití | Nejvhodnější pro |
|---|---|---|
DataRow |
Vestavěná testovací data | Jednoduché, statické testovací případy |
DynamicData |
Data z metod, vlastností nebo polí | Složitá nebo vypočítaná testovací data |
DataSource |
Externí datové soubory nebo databáze | Starší scénáře s externími zdroji dat |
MSTest také poskytuje následující typy pro rozšíření scénářů řízených daty:
-
TestDataRow<T>: Návratový typ proITestDataSourceimplementace (včetněDynamicData) přidává podporu metadat, jako jsou zobrazované názvy, kategorie a ignorování zpráv do jednotlivých testovacích případů. -
ITestDataSource: Rozhraní, které můžete implementovat pro vlastní atribut a vytvořit plně vlastní atributy zdroje dat.
Návod
Pro kombinatorické testování (testování všech kombinací více sad parametrů) použijte opensourcový balíček Combinatorial.MSTest NuGet. Tento komunitní balíček je k dispozici na GitHubu , ale microsoft ho neudržuje.
DataRowAttribute
Umožňuje DataRowAttribute spustit stejnou testovací metodu s několika různými vstupy. Použijte jeden nebo více DataRow atributů na testovací metodu, která je označená TestMethodAttribute.
Počet a typy argumentů musí přesně odpovídat podpisu testovací metody.
Návod
Související analyzátory:
-
MSTEST0014 ověří, že
DataRowargumenty odpovídají podpisu testovací metody. -
MSTEST0042 zjistí duplicitní
DataRowpoložky, které by spustily stejný testovací případ vícekrát.
Základní použití
[TestClass]
public class CalculatorTests
{
[TestMethod]
[DataRow(1, 2, 3)]
[DataRow(0, 0, 0)]
[DataRow(-1, 1, 0)]
[DataRow(100, 200, 300)]
public void Add_ReturnsCorrectSum(int a, int b, int expected)
{
var calculator = new Calculator();
Assert.AreEqual(expected, calculator.Add(a, b));
}
}
Podporované typy argumentů
DataRow podporuje různé typy argumentů, včetně primitiv, řetězců, polí a hodnot null:
[TestClass]
public class DataRowExamples
{
[TestMethod]
[DataRow(1, "message", true, 2.0)]
public void TestWithMixedTypes(int i, string s, bool b, float f)
{
// Test with different primitive types
}
[TestMethod]
[DataRow(new string[] { "line1", "line2" })]
public void TestWithArray(string[] lines)
{
Assert.AreEqual(2, lines.Length);
}
[TestMethod]
[DataRow(null)]
public void TestWithNull(object o)
{
Assert.IsNull(o);
}
[TestMethod]
[DataRow(new string[] { "a", "b" }, new string[] { "c", "d" })]
public void TestWithMultipleArrays(string[] input, string[] expected)
{
// Starting with MSTest v3, two arrays don't need wrapping
}
}
Poznámka:
Od verze MSTest v3.10 používejte DateOnly a TimeOnly jako argumenty DataRow a v parametrizovaných testech DynamicData.
Použití parametrů pro argumenty proměnných
Pomocí klíčového params slova můžete přijmout proměnný počet argumentů:
[TestClass]
public class ParamsExample
{
[TestMethod]
[DataRow(1, 2, 3, 4)]
[DataRow(10, 20)]
[DataRow(5)]
public void TestWithParams(params int[] values)
{
Assert.IsTrue(values.Length > 0);
}
}
Obecné testovací metody
Počínaje verzí MSTest v3.8 TestMethod může mít parametry typu. Rámec odvodí argumenty typu z hodnot DataRow nebo DynamicData:
[TestMethod]
[DataRow(42)]
[DataRow("alpha")]
public void Value_RoundTrips<T>(T value)
{
Assert.AreEqual(value, value);
}
Vlastní zobrazované názvy
DisplayName Nastavte vlastnost tak, aby se přizpůsobila zobrazení testovacích případů v Průzkumníku testů:
[TestClass]
public class DisplayNameExample
{
[TestMethod]
[DataRow(1, 2, DisplayName = "Functional Case FC100.1")]
[DataRow(3, 4, DisplayName = "Edge case: small numbers")]
public void TestMethod(int i, int j)
{
Assert.IsTrue(i < j);
}
}
Návod
Pokud chcete mít větší kontrolu nad testovacími metadaty, zvažte použití testDataRow<T> s DynamicData.
TestDataRow<T> podporuje zobrazování názvů spolu s kategoriemi testů a ignorované zprávy pro jednotlivé testovací případy.
Ignorování konkrétních testovacích případů
Počínaje verzí MSTest v3.8 pomocí IgnoreMessage vlastnosti přeskočte konkrétní datové řádky:
[TestClass]
public class IgnoreDataRowExample
{
[TestMethod]
[DataRow(1, 2)]
[DataRow(3, 4, IgnoreMessage = "Temporarily disabled - bug #123")]
[DataRow(5, 6)]
public void TestMethod(int i, int j)
{
// Only the first and third data rows run
// The second is skipped with the provided message
}
}
DynamicDataAttribute
Umožňuje DynamicDataAttribute poskytovat testovací data z metod, vlastností nebo polí. Tento atribut použijte, pokud jsou testovací data složitá, dynamicky vypočítaná nebo příliš podrobná pro vložené DataRow atributy.
Podporované typy zdrojů dat
Zdroj dat může vrátit libovolný IEnumerable<T>, u kterého T je jedním z typů uvedených v následující tabulce. Jakákoli kolekce implementující IEnumerable<T> funguje, včetně List<T>, polí jako T[], nebo vlastních typů kolekcí. Vyberte si podle svých potřeb:
| Návratový typ | Typová bezpečnost | Podpora metadat | Nejvhodnější pro |
|---|---|---|---|
ValueTuple (například (int, string)) |
Čas kompilace | Ne | Většina scénářů – jednoduchá syntaxe s úplnou kontrolou typů |
Tuple<...> |
Čas kompilace | Ne | Když nemůžete použít ValueTuple |
TestDataRow<T> |
Čas kompilace | Ano | Testovací případy vyžadující zobrazované názvy, kategorie nebo ignorování zpráv |
object[] |
Pouze modul runtime | Ne | Starší verze kódu – vyhněte se novým testům |
Návod
U nových metod testovacích dat použijte ValueTuple pro jednoduché případy nebo TestDataRow<T> v případě, že potřebujete metadata. Vyhněte se object[], protože chybí kontrola typů během kompilace a může způsobit chyby během spuštění z neshod typů.
Zdroje dat
Zdrojem dat může být metoda nebo vlastnost a počínaje msTest v3.11 pole. Tyto zdroje jsou zaměnitelné, takže zvolte podle svých preferencí:
Poznámka:
Počínaje verzí MSTest v3.8 DynamicData automaticky rozpozná typ zdroje dat. Nemusíte explicitně zadávat DynamicDataSourceType .
[TestClass]
public class DynamicDataExample
{
// Method - best for computed or yielded data
public static IEnumerable<(int Value, string Name)> GetTestData()
{
yield return (1, "first");
yield return (2, "second");
}
// Property - concise for static data
public static IEnumerable<(int Value, string Name)> TestDataProperty =>
[
(1, "first"),
(2, "second")
];
// Field - simplest for static data
public static IEnumerable<(int Value, string Name)> TestDataField =
[
(1, "first"),
(2, "second")
];
[TestMethod]
[DynamicData(nameof(GetTestData))]
public void TestWithMethod(int value, string name)
{
Assert.IsTrue(value > 0);
}
[TestMethod]
[DynamicData(nameof(TestDataProperty))]
public void TestWithProperty(int value, string name)
{
Assert.IsTrue(value > 0);
}
[TestMethod]
[DynamicData(nameof(TestDataField))]
public void TestWithField(int value, string name)
{
Assert.IsTrue(value > 0);
}
}
Poznámka:
Metody, vlastnosti a pole zdroje dat musí být public static a vracet IEnumerable<T> podporovaného typu.
Poznámka:
Počínaje verzí MSTest v3.11 může být zdrojem dat pole. Starší verze podporují metody a vlastnosti.
Návod
Související analyzátor: MSTEST0018 ověří, že zdroj dat existuje, je přístupný a má správný podpis.
Zdroj dat z jiné třídy
Zadejte jinou třídu pomocí parametru typu:
public class TestDataProvider
{
public static IEnumerable<(int, string)> GetTestData()
{
yield return (1, "first");
yield return (2, "second");
}
}
[TestClass]
public class DynamicDataExternalExample
{
[TestMethod]
[DynamicData(nameof(TestDataProvider.GetTestData), typeof(TestDataProvider))]
public void TestMethod(int value1, string value2)
{
Assert.IsTrue(value1 > 0);
}
}
Parametrizované DynamicData zdrojové metody
Od verze MSTest 3.10 předejte hodnoty metodě zdroje DynamicData pomocí vlastnosti Arguments:
[TestMethod]
[DynamicData(nameof(GetValues), Arguments = new object[] { true })]
public void Value_IsPositive(int value, bool expected) => Assert.AreEqual(expected, value > 0);
public static IEnumerable<(int Value, bool Expected)> GetValues(bool includeZero) =>
includeZero ? [(1, true), (0, false)] : [(1, true)];
Vlastní zobrazované názvy
Přizpůsobte zobrazované názvy testovacích DynamicDataDisplayName případů pomocí vlastnosti:
using System.Reflection;
[TestClass]
public class DynamicDataDisplayNameExample
{
[TestMethod]
[DynamicData(nameof(GetTestData), DynamicDataDisplayName = nameof(GetDisplayName))]
public void TestMethod(int value1, string value2)
{
Assert.IsTrue(value1 > 0);
}
public static IEnumerable<(int, string)> GetTestData()
{
yield return (1, "first");
yield return (2, "second");
}
public static string GetDisplayName(MethodInfo methodInfo, object[] data)
{
return $"{methodInfo.Name} with value {data[0]} and '{data[1]}'";
}
}
Poznámka:
Metoda zobrazovaného názvu musí být public static, vrátit stringa přijmout dva parametry: MethodInfo a object[].
Návod
Pro jednodušší přístup k vlastním zobrazovaným názvům zvažte použití TestDataRow<T> s jeho DisplayName vlastností místo samostatné metody.
Ignorování všech testovacích případů ze zdroje dat
Počínaje verzí MSTest v3.8 použijte IgnoreMessage ke přeskočení všech testovacích případů:
[TestClass]
public class IgnoreDynamicDataExample
{
[TestMethod]
[DynamicData(nameof(GetTestData), IgnoreMessage = "Feature not ready")]
public void TestMethod(int value1, string value2)
{
// All test cases from GetTestData are skipped
}
public static IEnumerable<(int, string)> GetTestData()
{
yield return (1, "first");
yield return (2, "second");
}
}
Návod
Chcete-li ignorovat jednotlivé testovací případy, použijte TestDataRow<T> s jeho IgnoreMessage vlastností. Viz část TestDataRow<T> .
TestDataRow
Třída TestDataRow<T> poskytuje vylepšenou kontrolu nad testovacími daty v testech řízených daty. Použijte IEnumerable<T> typu TestDataRow<T> jako návratový typ zdroje dat pro zadání:
Poznámka:
MSTest byl představen TestDataRow<T> ve verzi 3.8.
- Vlastní zobrazované názvy: Nastavte jedinečný zobrazovaný název podle testovacího DisplayName případu pomocí vlastnosti.
- Kategorie testů: Připojte metadata k jednotlivým testovacím případům pomocí TestCategories vlastnosti.
- Ignorovat zprávy: Přeskočte konkrétní testovací případy a uveďte důvody pomocí vlastnosti IgnoreMessage.
- Typově bezpečná data: Pro testovací data silného typu používejte obecné typy.
Základní použití
[TestClass]
public class TestDataRowExample
{
[TestMethod]
[DynamicData(nameof(GetTestDataRows))]
public void TestMethod(int value1, string value2)
{
Assert.IsTrue(value1 > 0);
}
public static IEnumerable<TestDataRow<(int, string)>> GetTestDataRows()
{
yield return new TestDataRow<(int, string)>((1, "first"))
{
DisplayName = "Test Case 1: Basic scenario",
};
yield return new TestDataRow<(int, string)>((2, "second"))
{
DisplayName = "Test Case 2: Edge case",
TestCategories = ["HighPriority", "Critical"],
};
yield return new TestDataRow<(int, string)>((3, "third"))
{
IgnoreMessage = "Not yet implemented",
};
}
}
DataSourceAttribute
Poznámka:
DataSource je k dispozici pouze v rozhraní .NET Framework. Pro projekty .NET (Core) použijte DataRow nebo DynamicData místo něj.
Testy DataSourceAttribute se připojují k externím zdrojům dat, jako jsou soubory CSV, soubory XML nebo databáze.
Podrobné informace najdete tady:
ITestDataSource
Rozhraní ITestDataSource umožňuje vytvářet zcela vlastní atributy zdroje dat. Toto rozhraní implementujte, pokud potřebujete chování, které předdefinované atributy nepodporují, například generování testovacích dat na základě proměnných prostředí, konfiguračních souborů nebo jiných podmínek modulu runtime.
Členy rozhraní
Rozhraní definuje dvě metody:
| Metoda | Účel |
|---|---|
GetData(MethodInfo) |
Vrátí testovací data jako IEnumerable<object?[]> |
GetDisplayName(MethodInfo, object?[]?) |
Vrátí zobrazovaný název testovacího případu. |
Vytvoření vlastního atributu zdroje dat
Pokud chcete vytvořit vlastní zdroj dat, definujte třídu atributů, která dědí z Attribute a implementuje ITestDataSource:
using System.Globalization;
using System.Reflection;
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class MyDataSourceAttribute : Attribute, ITestDataSource
{
public IEnumerable<object?[]> GetData(MethodInfo methodInfo)
{
// Return test data based on your custom logic
yield return [1, "first"];
yield return [2, "second"];
yield return [3, "third"];
}
public string? GetDisplayName(MethodInfo methodInfo, object?[]? data)
{
return data is null
? null
: string.Format(CultureInfo.CurrentCulture, "{0} ({1})", methodInfo.Name, string.Join(",", data));
}
}
[TestClass]
public class CustomDataSourceExample
{
[TestMethod]
[MyDataSource]
public void TestWithCustomDataSource(int value, string name)
{
Assert.IsTrue(value > 0);
Assert.IsNotNull(name);
}
}
Příklad z reálného světa: Testovací data založená na prostředí
Tento příklad ukazuje vlastní atribut, který generuje testovací data na základě cílových architektur a filtrování na základě operačního systému:
using System.Globalization;
using System.Reflection;
[AttributeUsage(AttributeTargets.Method)]
public class TargetFrameworkDataAttribute : Attribute, ITestDataSource
{
private readonly string[] _frameworks;
public TargetFrameworkDataAttribute(params string[] frameworks)
{
_frameworks = frameworks;
}
public IEnumerable<object?[]> GetData(MethodInfo methodInfo)
{
bool isWindows = OperatingSystem.IsWindows();
foreach (string framework in _frameworks)
{
// Skip .NET Framework on non-Windows platforms
if (!isWindows && framework.StartsWith("net4", StringComparison.Ordinal))
{
continue;
}
yield return [framework];
}
}
public string? GetDisplayName(MethodInfo methodInfo, object?[]? data)
{
return data is null
? null
: string.Format(CultureInfo.CurrentCulture, "{0} ({1})", methodInfo.Name, data[0]);
}
}
[TestClass]
public class CrossPlatformTests
{
[TestMethod]
[TargetFrameworkData("net48", "net8.0", "net9.0")]
public void TestOnMultipleFrameworks(string targetFramework)
{
// Test runs once per applicable framework
Assert.IsNotNull(targetFramework);
}
}
Návod
V jednoduchých případech, kdy stačí přizpůsobit zobrazované názvy nebo přidat metadata, zvažte použití TestDataRow<T> místo DynamicData implementace ITestDataSource. Vyhraďte si vlastní ITestDataSource implementace pro scénáře, které vyžadují dynamické filtrování nebo komplexní logiku generování dat.
Strategie odhalování
Atributy testů řízené daty podporují TestDataSourceUnfoldingStrategy vlastnost, která řídí, jak se testovací případy zobrazují v Průzkumníku testů a výsledcích TRX. Tato vlastnost také určuje, zda můžete spustit jednotlivé testovací případy nezávisle.
Fáze zjišťování a provádění
MSTest zpracovává testy řízené daty ve dvou různých fázích:
-
Fáze zjišťování: MSTest vyhodnotí všechny atributy zdroje dat (
DataRow,DynamicData,ITestDataSource) k určení seznamu testovacích případů. K tomuto vyhodnocení dochází před spuštěním všech běžných háků životního cyklu MSTest—AssemblyInitialize,ClassInitializea další metody nastavení se ještě nespustily. - Fáze provádění: MSTest spustí normální životní cyklus (inicializace sestavení, inicializace třídy, inicializace testů, testovací metoda, vyčištění) a spustí každý testovací případ s jejími daty.
Vzhledem k tomu, že se zdroje dat vyhodnocují během zjišťování, kód generování dat nemůže spoléhat na žádný stav nastavený AssemblyInitialize nebo ClassInitialize. Pokud váš zdroj dat závisí na logice nastavení (například čtení z připojení k databázi inicializované v ClassInitialize), vyhodnocení zdroje dat se během zjišťování nezdaří.
Dostupné strategie
| Strategie | Chování |
|---|---|
Auto (výchozí) |
MSTest určuje nejlepší strategii pro rozvinutí. |
Unfold |
Všechny testovací případy jsou rozbaleny a zobrazeny jednotlivě. |
Fold |
Všechny testovací případy jsou sloučeny do jednoho testovacího uzlu. |
Složené vs. rozložené testy
Strategie rozbalení ovlivňuje způsob, jakým jsou výsledky testů hlášeny v Test Exploreru a ve výstupu TRX.
- Rozbalené testy: Každý datový řádek se zobrazí jako samostatný nezávislý testovací záznam v Průzkumníku testů a TRX. Můžete spouštět, ladit nebo filtrovat jednotlivé testovací případy. Každá položka má svůj vlastní stav pass/fail.
- Složené testy: Všechny řádky dat se v Průzkumníku testů zobrazí jako jeden testovací uzel. V TRX se zobrazí jedna položka s více výsledky přidruženými k jednomu testovacímu případu. Jednotlivé řádky dat nelze spouštět ani filtrovat nezávisle.
Výjimka při zjišťování způsobuje posouvání
Když MSTest vyhodnotí zdroj dat během zjišťování a vyhodnocení vyvolá výjimku, test se vrátí do přeloženého stavu bez ohledu na nakonfigurovanou strategii rozbalení. Vzhledem k tomu, že architektura nemůže vytvořit výčet jednotlivých testovacích případů, zaregistruje testovací metodu jako jednu (složenou) položku.
V době provádění nástroj MSTest vyhodnotí zdroj dat znovu jako součást normálního životního cyklu. Pokud byla výjimka způsobená chybějícím stavem instalace (například závislostí, kterou ClassInitialize poskytuje), může být zdroj dat při provádění úspěšný, protože nyní proběhly události životního cyklu.
Poznámka:
Při ladění testu, který vyvolává výjimku během zjišťování chyb, se může před spuštěním testu zobrazit výjimka (například NullReferenceException). Tato výjimka pochází z vyhodnocení fáze zjišťování. Stiskněte pokračovat v ladicím programu – test se pak spustí normálně, protože fáze provádění spouští celý životní cyklus MSTest, včetně inicializačních metod. Další podrobnosti najdete v microsoft/testfx#7774.
Kdy změnit strategii
Ve většině scénářů poskytuje výchozí Auto chování nejlepší rovnováhu. Zvažte změnu strategie nasazení, pokud máte specifické požadavky:
- Použijte
Fold, pokud zdroje dat závisí na stavu modulu runtime nebo na logice nastavení, která není během zjišťování dostupná. - Používá se
Foldpro ne deterministické zdroje dat, které při každém vyhodnocení vrací různé hodnoty. - Použijte
Foldke snížení zatížení, pokud je výkon důležitý při práci s velkým počtem testovacích případů.
Příklad využití
[TestClass]
public class UnfoldingExample
{
[TestMethod(UnfoldingStrategy = TestDataSourceUnfoldingStrategy.Unfold)] // That's the default behavior
[DataRow(1, "one")]
[DataRow(2, "two")]
[DataRow(3, "three")]
public void TestMethodWithUnfolding(int value, string text)
{
// Each test case appears individually in Test Explorer
}
[TestMethod(UnfoldingStrategy = TestDataSourceUnfoldingStrategy.Fold)]
[DataRow(1, "one")]
[DataRow(2, "two")]
[DataRow(3, "three")]
public void TestMethodWithFolding(int value, string text)
{
// All test cases appear as a single collapsed node
}
}
Osvědčené postupy
-
Zvolte správný atribut: Použijte
DataRowpro jednoduchá vložená data. Používá seDynamicDatapro složitá nebo vypočítaná data. -
Pojmenujte testovací případy: Umožňuje
DisplayNameusnadnit identifikaci selhání testů. - Zachovat zdroje dat blízko: Pokud je to možné, definujte zdroje dat ve stejné třídě, aby bylo možné lépe udržovat.
- Používejte smysluplná data: Zvolte testovací data, která testují mezní případy a okrajové podmínky.
- Zvažte kombinatorické testování: Pro kombinace parametrů testování použijte balíček Combinatorial.MSTest .