Not
Åtkomst till denna sida kräver auktorisation. Du kan prova att logga in eller byta katalog.
Åtkomst till denna sida kräver auktorisation. Du kan prova att byta katalog.
Med datadriven testning kan du köra samma testmetod med flera uppsättningar indata. I stället för att skriva separata testmetoder för varje testfall definierar du testlogik en gång och anger olika indata via attribut eller externa datakällor.
Översikt
MSTest innehåller flera attribut för datadriven testning:
| Attribute | Användningsfall | Passar bäst för |
|---|---|---|
DataRow |
Inlinje testdata | Enkla, statiska testfall |
DynamicData |
Data från metoder, egenskaper eller fält | Komplexa eller beräknade testdata |
TestDataRow<T> |
Förbättrade data med metadata | Testfall som behöver visningsnamn eller kategorier |
DataSource |
Externa datafiler eller databaser | Äldre scenarier med externa datakällor |
ITestDataSource |
Attribut för anpassad datakälla | Fullständigt anpassade datadrivna scenarier |
Tips/Råd
För kombinatoriell testning (testa alla kombinationer av flera parameteruppsättningar) använder du combinatorial.MSTest NuGet-paketet med öppen källkod. Det här community-underhållna paketet är tillgängligt på GitHub men underhålls inte av Microsoft.
DataRowAttribute
Gör DataRowAttribute att du kan köra samma testmetod med flera olika indata. Använd ett eller flera DataRow attribut på en testmetod och kombinera det med TestMethodAttribute.
Antalet och typerna av argument måste exakt matcha testmetodens signatur.
Tips/Råd
Relaterade analysverktyg:
-
MSTEST0014 verifierar att
DataRowargumenten matchar testmetodens signatur. -
MSTEST0042 identifierar duplicerade
DataRowposter som skulle köra samma testfall flera gånger.
Grundläggande användning
[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));
}
}
Argumenttyper som stöds
DataRow stöder olika argumenttyper, inklusive primitiver, strängar, matriser och null-värden:
[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
}
}
Använda params för variabelargument
Använd nyckelordet params för att acceptera ett variabelt antal 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);
}
}
Anpassade visningsnamn
Ange egenskapen DisplayName för att anpassa hur testfall visas i Test Explorer:
[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);
}
}
Tips/Råd
Om du vill ha mer kontroll över testmetadata bör du överväga att använda TestDataRow<T> med DynamicData.
TestDataRow<T> stöder visningsnamn tillsammans med testkategorier och ignorerar meddelanden för enskilda testfall.
Ignorera specifika testfall
Från och med MSTest v3.8 använder du IgnoreMessage egenskapen för att hoppa över specifika datarader:
[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
Med DynamicDataAttribute kan du ange testdata från metoder, egenskaper eller fält. Använd det här attributet när testdata är komplexa, beräknade dynamiskt eller för utförliga för infogade DataRow attribut.
Typer av datakällor som stöds
Datakällan kan returnera var som helst IEnumerable<T> där T är en av de typer som anges i följande tabell. Alla samlingar som implementerar IEnumerable<T> fungerar, inklusive List<T>, arrayer som T[], eller anpassade samlingstyper. Välj baserat på dina behov:
| Returtyp | Typsäkerhet | Stöd för metadata | Passar bäst för |
|---|---|---|---|
ValueTuple (till exempel (int, string)) |
Kompileringstid | Nej | De flesta scenarier – enkel syntax med fullständig typkontroll |
Tuple<...> |
Kompileringstid | Nej | När du inte kan använda ValueTuple |
TestDataRow<T> |
Kompileringstid | Yes | Testfall som behöver visningsnamn, kategorier eller ignorera meddelanden |
object[] |
Endast körningstid | Nej | Äldre kod – undvik för nya tester |
Tips/Råd
För nya testdatametoder använder ValueTuple du för enkla fall eller TestDataRow<T> när du behöver metadata. Undvik object[] eftersom den saknar typkontroll under kompilering och kan orsaka körningsfel från typer som inte matchar.
Datakällor
Datakällan kan vara en metod, egenskap eller ett fält. Alla tre är utbytbara – välj baserat på dina önskemål:
[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);
}
}
Anmärkning
Datakällans metoder, egenskaper och fält måste vara public static och returnera en IEnumerable<T> av en typ som stöds.
Tips/Råd
Relaterat analysverktyg: MSTEST0018 verifierar att datakällan finns, är tillgänglig och har rätt signatur.
Datakälla från en annan klass
Ange en annan klass med hjälp av typparametern:
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);
}
}
Anpassade visningsnamn
Anpassa visningsnamn för testfall med hjälp av DynamicDataDisplayName egenskapen:
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]}'";
}
}
Anmärkning
Visningsnamnmetoden måste vara public static, returnera en stringoch acceptera två parametrar: MethodInfo och object[].
Tips/Råd
Om du vill ha en enklare metod för anpassade visningsnamn bör du överväga att använda TestDataRow<T> med dess DisplayName egenskap i stället för en separat metod.
Ignorera alla testfall från en datakälla
Från och med MSTest v3.8 kan du använda IgnoreMessage för att hoppa över alla testfall:
[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" };
}
}
Tips/Råd
Om du vill ignorera enskilda testfall använder du TestDataRow<T> med dess IgnoreMessage egenskap. Se avsnittet TestDataRow<T> .
TestDataRow
Klassen TestDataRow<T> ger förbättrad kontroll över testdata i datadrivna tester. Använd IEnumerable<TestDataRow<T>> som returtyp för datakällan för att ange:
- Anpassade visningsnamn: Ange ett unikt visningsnamn per testfall
- Testkategorier: Koppla metadata till enskilda testfall
- Ignorera meddelanden: Hoppa över specifika testfall med orsaker
- Typsäkra data: Använd generiska objekt för starkt typade testdata
Grundläggande användning
[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
Anmärkning
DataSource är endast tillgängligt i .NET Framework. För .NET Core-projekt, använd DataRow eller DynamicData i stället.
DataSourceAttribute Ansluter tester till externa datakällor som CSV-filer, XML-filer eller databaser.
Detaljerad information finns här:
ITestDataSource
Med ITestDataSource gränssnittet kan du skapa helt anpassade datakällans attribut. Implementera det här gränssnittet när du behöver beteende som de inbyggda attributen inte stöder, till exempel att generera testdata baserat på miljövariabler, konfigurationsfiler eller andra körningsvillkor.
Gränssnittsmedlemmar
Gränssnittet definierar två metoder:
| Metod | Avsikt |
|---|---|
GetData(MethodInfo) |
Returnerar testdata som IEnumerable<object?[]> |
GetDisplayName(MethodInfo, object?[]?) |
Returnerar visningsnamnet för ett testfall |
Skapa ett anpassat datakällaattribut
Om du vill skapa en anpassad datakälla definierar du en attributklass som ärver från Attribute och implementerar 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);
}
}
Verkligt exempel: Miljöbaserade testdata
Det här exemplet visar ett anpassat attribut som genererar testdata baserat på målramverk, filtrering baserat på operativsystemet:
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);
}
}
Tips/Råd
För enkla fall där du bara behöver anpassa visningsnamn eller lägga till metadata kan du överväga att använda TestDataRow<T> med DynamicData i stället för att implementera ITestDataSource. Reservera anpassade ITestDataSource implementeringar för scenarier som kräver dynamisk filtrering eller komplex datagenereringslogik.
Avvecklande strategi
Datadrivna testattribut stöder TestDataSourceUnfoldingStrategy egenskapen, som styr hur testfall visas i Test Explorer och TRX-resultat. Den här egenskapen avgör också om du kan köra enskilda testfall oberoende av varandra.
Tillgängliga strategier
| Strategi | Beteende |
|---|---|
Auto (standardinställning) |
MSTest avgör hur den bästa strategin utvecklas |
Unfold |
Alla testfall expanderas och visas individuellt |
Fold |
Alla testfall komprimeras till en enskild testnod |
När du ska ändra strategin
För de flesta scenarier ger standardbeteendet Auto den bästa balansen. Överväg att bara ändra den här inställningen när du har specifika krav:
- Icke-deterministiska datakällor
- Kända begränsningar eller buggar i MSTest
- Prestandaproblem med många testfall
Exempel på användning
[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");
}
}
Metodtips
Välj rätt attribut: Använd
DataRowför enkla, infogade data. AnvändsDynamicDataför komplexa eller beräknade data.Namnge dina testfall: Använd
DisplayNameför att göra testfel enklare att identifiera.Håll datakällorna nära: Definiera datakällor i samma klass när det är möjligt för bättre underhåll.
Använd meningsfulla data: Välj testdata som utför gränsfall och gränsvillkor.
Överväg kombinatoriell testning: Använd combinatorial.MSTest-paketet för att testa parameterkombinationer.