Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Mit datengesteuerten Tests können Sie dieselbe Testmethode mit mehreren Eingabedatensätzen ausführen. Anstatt separate Testmethoden für jeden Testfall zu schreiben, definieren Sie ihre Testlogik einmal, und stellen Sie verschiedene Eingaben über Attribute oder externe Datenquellen bereit.
Überblick
MSTest bietet mehrere Attribute für datengesteuerte Tests:
| Merkmal | Anwendungsfall | Am besten geeignet für: |
|---|---|---|
DataRow |
Inlinetestdaten | Einfache, statische Testfälle |
DynamicData |
Daten aus Methoden, Eigenschaften oder Feldern | Komplexe oder berechnete Testdaten |
TestDataRow<T> |
Erweiterte Daten mit Metadaten | Testfälle, die Anzeigenamen oder Kategorien benötigen |
DataSource |
Externe Datendateien oder Datenbanken | Altsystem-Szenarien mit externen Datenquellen |
ITestDataSource |
Benutzerdefinierte Datenquellenattribute | Vollständig benutzerdefinierte datengesteuerte Szenarien |
Tipp
Verwenden Sie zum Kombinieren von Tests (testen aller Kombinationen mehrerer Parametersätze) das Open-Source-Paket Combinatorial.MSTest NuGet. Dieses von der Community verwaltete Paket ist auf GitHub verfügbar , wird jedoch nicht von Microsoft verwaltet.
DataRowAttribute
Auf DataRowAttribute diese Weise können Sie dieselbe Testmethode mit mehreren verschiedenen Eingaben ausführen. Wenden Sie ein oder mehrere DataRow Attribute auf eine Testmethode an, und kombinieren Sie es mit der TestMethodAttribute.
Die Anzahl von Argumenten und die Argumenttypen müssen genau mit der Testmethodensignatur übereinstimmen.
Tipp
Verwandte Analysegeräte:
-
MSTEST0014 überprüft, ob
DataRowArgumente der Signatur der Testmethode entsprechen. -
MSTEST0042 erkennt doppelte
DataRowEinträge, die denselben Testfall mehrmals ausführen würden.
Grundlegende Nutzung
[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));
}
}
Unterstützte Argumenttypen
DataRow unterstützt verschiedene Argumenttypen wie Grundtypen, Zeichenfolgen, Arrays und Nullwerte:
[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
}
}
Verwenden von Params für variablen Argumente
Verwenden Sie das params Schlüsselwort, um eine variable Anzahl von Argumenten zu akzeptieren:
[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);
}
}
Benutzerdefinierte Anzeigenamen
Legen Sie die DisplayName Eigenschaft fest, um anzupassen, wie Testfälle im Test-Explorer angezeigt werden:
[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);
}
}
Tipp
Um mehr Kontrolle über Testmetadaten zu haben, erwägen Sie die Verwendung von TestDataRow<T> mit DynamicData.
TestDataRow<T> unterstützt Anzeigenamen zusammen mit Testkategorien und das Ignorieren von Meldungen für die einzelnen Testfälle.
Ignorieren bestimmter Testfälle
Verwenden Sie ab MSTest v3.8 die IgnoreMessage Eigenschaft, um bestimmte Datenzeilen zu überspringen:
[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
Auf diese DynamicDataAttribute Weise können Sie Testdaten aus Methoden, Eigenschaften oder Feldern bereitstellen. Verwenden Sie dieses Attribut, wenn Testdaten komplex, dynamisch berechnet oder zu ausführlich für Inlineattribute DataRow sind.
Unterstützte Datenquellentypen
Die Datenquelle kann jedes IEnumerable<T> zurückgeben, wobei T einer der in der folgenden Tabelle aufgeführten Typen ist. Jede Sammlung, die IEnumerable<T> implementiert, funktioniert, einschließlich List<T>, Arrays wie T[] oder benutzerdefinierter Sammlungstypen. Wählen Sie basierend auf Ihren Anforderungen aus:
| Rückgabetyp | Typsicherheit | Metadatenunterstützung | Am besten geeignet für: |
|---|---|---|---|
ValueTuple (z. B. (int, string)) |
Kompilierungszeit | Nein | Die meisten Szenarien – einfache Syntax mit vollständiger Typüberprüfung |
Tuple<...> |
Kompilierungszeit | Nein | Wenn Sie ValueTuple nicht verwenden können |
TestDataRow<T> |
Kompilierungszeit | Yes | Testfälle, die Anzeigenamen, Kategorien oder Ignorieren von Nachrichten benötigen |
object[] |
Nur Laufzeit | Nein | Legacy-Code – für neue Tests vermeiden |
Tipp
Verwenden Sie ValueTuple für einfache Fälle oder TestDataRow<T>, wenn Metadaten benötigt werden, bei neuen Testdatenmethoden. Vermeiden Sie object[], da die Typüberprüfung zur Kompilierzeit fehlt und Laufzeitfehler aufgrund von Typinkompatibilitäten auftreten können.
Datenquellen
Die Datenquelle kann eine Methode, Eigenschaft oder ein Feld sein. Alle drei sind austauschbar – wählen Sie basierend auf Ihrer Einstellung aus:
[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);
}
}
Hinweis
Datenquellenmethoden, Eigenschaften und Felder müssen vom Typ public static sein und einen IEnumerable<T> eines unterstützten Typs zurückgeben.
Tipp
Verwandte Analyse: MSTEST0018 überprüft, ob die Datenquelle vorhanden ist, zugänglich ist und über die richtige Signatur verfügt.
Datenquelle aus einer anderen Klasse
Geben Sie eine andere Klasse mit dem Typparameter an:
public class TestDataProvider
{
public static IEnumerable<object[]> GetTestData()
{
yield return new object[] { 1, "first" };
yield return new object[] { 2, "second" };
}
}
[TestClass]
public class DynamicDataExternalExample
{
[TestMethod]
[DynamicData(nameof(TestDataProvider.GetTestData), typeof(TestDataProvider))]
public void TestMethod(int value1, string value2)
{
Assert.IsTrue(value1 > 0);
}
}
Benutzerdefinierte Anzeigenamen
Anpassen der Anzeigenamen von Testfällen mithilfe der DynamicDataDisplayName Eigenschaft:
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<object[]> GetTestData()
{
yield return new object[] { 1, "first" };
yield return new object[] { 2, "second" };
}
public static string GetDisplayName(MethodInfo methodInfo, object[] data)
{
return $"{methodInfo.Name} with value {data[0]} and '{data[1]}'";
}
}
Hinweis
Die Methode für den Anzeigenamen muss ein public static zurückgeben, ein string und zwei Parameter akzeptieren: MethodInfo und object[].
Tipp
Für einen einfacheren Ansatz für benutzerdefinierte Anzeigenamen sollten Sie TestDataRow<T> mit seiner DisplayName Eigenschaft anstelle einer separaten Methode verwenden.
Ignorieren aller Testfälle aus einer Datenquelle
Ab MSTest v3.8 können Sie alle Testfälle mit Hilfe von IgnoreMessage überspringen.
[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<object[]> GetTestData()
{
yield return new object[] { 1, "first" };
yield return new object[] { 2, "second" };
}
}
Tipp
Verwenden Sie TestDataRow<T> zusammen mit seiner Eigenschaft IgnoreMessage, um einzelne Testfälle zu ignorieren. Weitere Informationen finden Sie im Abschnitt "TestDataRow<T> ".
TestDataRow
Die TestDataRow<T> Klasse bietet erweiterte Kontrolle über Testdaten in datengesteuerten Tests. Verwenden Sie IEnumerable<TestDataRow<T>> den Rückgabetyp der Datenquelle, um Folgendes anzugeben:
- Benutzerdefinierte Anzeigenamen: Festlegen eines eindeutigen Anzeigenamens pro Testfall
- Testkategorien: Anfügen von Metadaten an einzelne Testfälle
- Ignorieren von Nachrichten: Überspringen bestimmter Testfälle mit Gründen
- Typsichere Daten: Verwenden von Generika für stark typierte Testdaten
Grundlegende Nutzung
[TestClass]
public class TestDataRowExample
{
[TestMethod]
[DynamicData(nameof(GetTestDataRows))]
public void TestMethod(int value1, string value2)
{
Assert.IsTrue(value1 > 0);
}
public static IEnumerable<TestDataRow> GetTestDataRows()
{
yield return new TestDataRow((1, "first"))
{
DisplayName = "Test Case 1: Basic scenario",
};
yield return new TestDataRow((2, "second"))
{
DisplayName = "Test Case 2: Edge case",
TestCategories = ["HighPriority", "Critical"],
};
yield return new TestDataRow((3, "third"))
{
IgnoreMessage = "Not yet implemented",
};
}
}
DataSourceAttribute
Hinweis
DataSource ist nur in .NET Framework verfügbar. Verwenden Sie stattdessen DataRow oder DynamicData für .NET (Core)-Projekte.
Der DataSourceAttribute verbindet Tests mit externen Datenquellen wie CSV-Dateien, XML-Dateien oder Datenbanken.
Ausführliche Informationen finden Sie unter:
- Erstellen eines datengesteuerten Komponententests
- Verwenden einer Konfigurationsdatei zum Definieren einer Datenquelle
ITestDataSource
Über die ITestDataSource Schnittstelle können Sie vollständig benutzerdefinierte Datenquellenattribute erstellen. Implementieren Sie diese Schnittstelle, wenn Sie Verhalten benötigen, das die integrierten Attribute nicht unterstützen, z. B. das Generieren von Testdaten basierend auf Umgebungsvariablen, Konfigurationsdateien oder anderen Laufzeitbedingungen.
Interface members (Schnittstellenmember)
Die Schnittstelle definiert zwei Methoden:
| Methode | Zweck |
|---|---|
GetData(MethodInfo) |
Gibt Testdaten als IEnumerable<object?[]> |
GetDisplayName(MethodInfo, object?[]?) |
Gibt den Anzeigenamen für einen Testfall zurück. |
Erstellen eines benutzerdefinierten Datenquellen-Attributs
Um eine benutzerdefinierte Datenquelle zu erstellen, definieren Sie eine Attributklasse, die von Attribute erbt und ITestDataSource implementiert.
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);
}
}
Reales Beispiel: Umgebungsbasierte Testdaten
Dieses Beispiel zeigt ein benutzerdefiniertes Attribut, das Testdaten basierend auf Zielframeworks generiert und basierend auf dem Betriebssystem gefiltert wird:
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);
}
}
Tipp
Für einfache Fälle, in denen Sie nur Anzeigenamen anpassen oder Metadaten hinzufügen müssen, sollten Sie TestDataRow<T> anstelle DynamicData der Implementierung ITestDataSourceverwenden. Reservieren Sie benutzerdefinierte ITestDataSource Implementierungen für Szenarien, die dynamische Filterung oder komplexe Logik für die Datengenerierung erfordern.
Entwicklungsstrategie
Datengesteuerte Testattribute unterstützen die TestDataSourceUnfoldingStrategy Eigenschaft, die steuert, wie Testfälle im Test-Explorer und TRX-Ergebnissen angezeigt werden. Diese Eigenschaft bestimmt auch, ob Einzelne Testfälle unabhängig voneinander ausgeführt werden können.
Verfügbare Strategien
| Strategie | Verhalten |
|---|---|
Auto (Standardwert) |
MSTest bestimmt, dass sich die beste Strategie entwickelt |
Unfold |
Alle Testfälle werden erweitert und einzeln angezeigt. |
Fold |
Alle Testfälle werden in einen einzigen Testknoten reduziert. |
Wann die Strategie geändert werden soll
Für die meisten Szenarien bietet das Standardverhalten Auto das beste Gleichgewicht. Erwägen Sie, diese Einstellung nur zu ändern, wenn Sie bestimmte Anforderungen haben:
- Nicht deterministische Datenquellen
- Bekannte Einschränkungen oder Fehler in MSTest
- Leistungsbedenken bei vielen Testfällen
Anwendungsbeispiel
[TestClass]
public class UnfoldingExample
{
[TestMethod(UnfoldingStrategy = TestDataSourceUnfoldingStrategy.Unfold)] // That's the default behavior
[DataRow(1)]
[DataRow(2)]
[DataRow(3)]
public void TestMethodWithUnfolding(int value, string text)
{
// Each test case appears individually in Test Explorer
}
[TestMethod(UnfoldingStrategy = TestDataSourceUnfoldingStrategy.Fold)]
[DynamicData(nameof(GetData))]
public void TestMethodWithFolding(int value, string text)
{
// All test cases appear as a single collapsed node
}
public static IEnumerable<(int, string)> GetData()
{
yield return (1, "one");
yield return (2, "two");
yield return (3, "three");
}
}
Bewährte Methoden
Wählen Sie das richtige Attribut aus: Wird für einfache Inlinedaten verwendet
DataRow. Verwenden SieDynamicDatafür komplexe oder berechnete Daten.Benennen Sie Ihre Testfälle: Verwenden Sie die Verwendung
DisplayName, um Testfehler einfacher zu identifizieren.Schließen Sie Datenquellen: Definieren Sie Datenquellen in derselben Klasse, wenn möglich, um eine bessere Wartung zu ermöglichen.
Verwenden Sie aussagekräftige Daten: Wählen Sie Testdaten aus, die Randfälle und Grenzbedingungen üben.
Erwägen Sie kombinatorische Tests: Verwenden Sie zum Testen von Parameterkombinationen das Paket Combinatorial.MSTest .