Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
Az adatvezérelt tesztelés lehetővé teszi ugyanazt a tesztmetódus futtatását több bemeneti adatkészlettel. Ahelyett, hogy külön tesztelési módszereket írnál minden egyes tesztesethez, definiáld egyszer a teszt logikáját, és adjon meg különböző bemeneteket attribútumokon vagy külső adatforrásokon keresztül.
Áttekintés
Az MSTest számos attribútumot biztosít az adatvezérelt teszteléshez:
| Attribute | Felhasználási eset | A következőkre alkalmas |
|---|---|---|
DataRow |
Beágyazott tesztadatok | Egyszerű, statikus tesztesetek |
DynamicData |
Metódusokból, tulajdonságokból vagy mezőkből származó adatok | Összetett vagy számított tesztadatok |
DataSource |
Külső adatfájlok vagy adatbázisok | Régi forgatókönyvek külső adatforrásokkal |
Az MSTest az alábbi típusokat is biztosítja az adatvezérelt forgatókönyvek kibővítéséhez:
-
TestDataRow<T>: Olyan implementációk visszatérésiITestDataSourcetípusa (beleértve a következőket isDynamicData), amelyek metaadat-támogatást adnak hozzá, például megjelenítendő neveket, kategóriákat és figyelmen kívül hagyják az egyes tesztesetekhez tartozó üzeneteket. -
ITestDataSource: Egy egyéni attribútumon implementálható felület, amely teljesen egyéni adatforrásattribútumokat hoz létre.
Jótanács
A kombinatorikus teszteléshez (több paraméterkészlet összes kombinációjának teszteléséhez) használja a nyílt forráskódú Combinatorial.MSTest NuGet-csomagot. Ez a közösség által fenntartott csomag elérhető a GitHubon , de a Microsoft nem tartja karban.
DataRowAttribute
Ez DataRowAttribute lehetővé teszi ugyanazt a tesztmetódus futtatását több különböző bemenettel. Alkalmazzon egy vagy több DataRow attribútumot egy tesztmetódusra, amely a TestMethodAttribute-vel van díszítve.
Az argumentumok számának és típusának pontosan meg kell egyeznie a vizsgálati módszer aláírásával.
Jótanács
Kapcsolódó elemzők:
-
MSTEST0014 ellenőrzi, hogy az argumentumok egyeznek-e
DataRowa tesztmetódus aláírásával. -
MSTEST0042 ismétlődő
DataRowbejegyzéseket észlel, amelyek ugyanazt a tesztesetet többször futtatnák.
Alapszintű használat
[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));
}
}
Támogatott argumentumtípusok
DataRow Különböző argumentumtípusokat támogat, például primitíveket, sztringeket, tömböket és null értékeket:
[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
}
}
Paramok használata változóargumentumokhoz
params A kulcsszóval változó számú argumentumot fogadhat el:
[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);
}
}
Egyéni megjelenítési nevek
Állítsa be a tulajdonságot a DisplayName tesztesetek megjelenésének testreszabásához a Test Explorerben:
[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);
}
}
Jótanács
A tesztelési metaadatok további szabályozásához fontolja meg a TestDataRow<T> használatát.DynamicData
TestDataRow<T> Támogatja a megjelenítendő neveket a tesztkategóriákkal együtt, és figyelmen kívül hagyja az egyes tesztesetekhez tartozó üzeneteket.
Adott tesztelési esetek figyelmen kívül hagyása
Az MSTest 3.8-s verziótól kezdve a IgnoreMessage tulajdonsággal kihagyhat bizonyos adatsorokat:
[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
Ez DynamicDataAttribute lehetővé teszi a metódusok, tulajdonságok vagy mezők tesztelési adatainak megadását. Ezt az attribútumot akkor használja, ha a tesztadatok összetettek, dinamikusan kiszámítottak vagy túl részletesek a beágyazott DataRow attribútumokhoz.
Támogatott adatforrástípusok
Az adatforrás visszaadhat bármilyen IEnumerable<T>, ahol T az alábbi táblázatban felsorolt típusok egyike. Bármely gyűjtemény, amely implementálja a IEnumerable<T>-t, működik, beleértve a List<T>, tömböket, mint például a T[], vagy egyéni gyűjteménytípusokat. Válasszon az igényei alapján:
| Visszatérési típus | Típusbiztonság | Metaadatok támogatása | A következőkre alkalmas |
|---|---|---|---|
ValueTuple (például: (int, string)) |
Fordítási idő | Nem | A legtöbb forgatókönyv – egyszerű szintaxis teljes típusellenőrzéssel |
Tuple<...> |
Fordítási idő | Nem | Ha nem tudja használni a ValueTuple |
TestDataRow<T> |
Fordítási idő | Igen | Megjelenítendő neveket, kategóriákat vagy üzenetek figyelmen kívül hagyását igénylő esetek tesztelése |
object[] |
Csak futásidejű környezet | Nem | Régi kód – ne használjon új teszteket |
Jótanács
Új tesztadat-módszerek esetén használja az ValueTuple egyszerű esetekhez, vagy az TestDataRow<T> amikor metaadatra van szükség. Kerülje object[], mert hiányzik belőle a fordítási idő alatti típusellenőrzés, és a típuseltérések futásidejű hibákat okozhatnak.
Adatforrások
Az adatforrás lehet metódus, tulajdonság vagy mező. Mindhárom felcserélhető – válassza a beállítások alapján:
[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);
}
}
Megjegyzés:
Az adatforrás metódusainak, tulajdonságainak és mezőinek támogatott típusú public static-nak kell lenniük, és egy IEnumerable<T>-t kell visszaadniuk.
Jótanács
Kapcsolódó elemző: MSTEST0018 ellenőrzi, hogy az adatforrás létezik-e, elérhető-e, és rendelkezik-e a megfelelő aláírással.
Adatforrás egy másik osztályból
Adjon meg egy másik osztályt a típusparaméterrel:
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);
}
}
Egyéni megjelenítési nevek
A tesztesetek megjelenítendő neveinek testreszabása a DynamicDataDisplayName tulajdonság használatával:
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]}'";
}
}
Megjegyzés:
A megjelenítési név metódusának egy értéket kell visszaadniapublic staticstring, és két paramétert kell elfogadnia: MethodInfo ésobject[].
Jótanács
Az egyéni megjelenítési nevek egyszerűbb megközelítéséhez fontolja meg a TestDataRow<T>DisplayName tulajdonságának használatát egy külön metódus helyett.
Az adatforrás összes tesztesetének figyelmen kívül hagyása
Az MSTest v3.8-as verziótól kezdve a IgnoreMessage minden teszteset kihagyására használható.
[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");
}
}
Jótanács
Az egyedi tesztesetek figyelmen kívül hagyásához használja a TestDataRow<T> szolgáltatást a IgnoreMessage tulajdonsággal. Lásd a TestDataRow<T> szakaszt.
TestDataRow
Az TestDataRow<T> osztály továbbfejlesztett vezérlést biztosít a tesztadatok felett az adatvezérelt tesztekben. A IEnumerable<T> és a TestDataRow<T> alkalmazása adattípusú visszatérési értékként az alábbiak meghatározásához:
- Egyéni megjelenítési nevek: Tesztesetenként egyedi megjelenítendő név beállítása a DisplayName tulajdonság használatával.
- Tesztkategóriák: Metaadatok csatolása a tulajdonságot használó egyes tesztelési TestCategories esetekhez.
- Üzenetek figyelmen kívül hagyása: Adott teszteseteket kihagyhat a IgnoreMessage tulajdonság használatával kapcsolatos indokokkal.
- Típusbiztos adatok: Általános adatok használata erősen gépelt tesztadatokhoz.
Alapszintű használat
[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
Megjegyzés:
DataSource csak a .NET-keretrendszerben érhető el. .NET (Core) projektekhez használja a DataRow vagy a DynamicData helyette.
A DataSourceAttribute teszteket külső adatforrásokhoz, például CSV-fájlokhoz, XML-fájlokhoz vagy adatbázisokhoz csatlakoztatja.
Részletes információkért lásd:
ITestDataSource
Az ITestDataSource interfész lehetővé teszi teljesen egyéni adatforrás-attribútumok létrehozását. Implementálja ezt az felületet, ha olyan viselkedésre van szüksége, amelyet a beépített attribútumok nem támogatnak, például tesztadatokat generál környezeti változók, konfigurációs fájlok vagy egyéb futtatókörnyezeti feltételek alapján.
Interfésztagok
Az interfész két módszert határoz meg:
| Metódus | Cél |
|---|---|
GetData(MethodInfo) |
Tesztadatokat ad vissza IEnumerable<object?[]> |
GetDisplayName(MethodInfo, object?[]?) |
Egy teszteset megjelenítendő nevét adja vissza |
Egyéni adatforrásattribútum létrehozása
Egyéni adatforrás létrehozásához definiáljon egy attribútumosztályt, amely a Attribute osztályt örökli, és a ITestDataSource interfészt implementálja.
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);
}
}
Valós példa: Környezetalapú tesztadatok
Ez a példa egy egyéni attribútumot mutat be, amely tesztadatokat hoz létre a cél-keretrendszerek alapján, az operációs rendszer alapján történő szűréssel:
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);
}
}
Jótanács
Olyan egyszerű esetekben, amikor csak testre kell szabnia a megjelenített neveket, vagy metaadatokat kell hozzáadnia, fontolja meg a TestDataRow<T>DynamicData használatát a implementálás ITestDataSourcehelyett. Használjon egyéni ITestDataSource implementációkat olyan forgatókönyvekhez, amelyek dinamikus szűrést vagy összetett adatlétrehozási logikát igényelnek.
A stratégia kibontása
Az adatvezérelt tesztattribútumok támogatják a TestDataSourceUnfoldingStrategy tulajdonságot, amely szabályozza, hogy a tesztesetek hogyan jelenjenek meg a Test Explorerben és a TRX-eredményekben. Ez a tulajdonság azt is meghatározza, hogy önállóan futtathat-e egyes teszteseteket.
Felderítési és végrehajtási fázisok
Az MSTest két különböző fázisban dolgozza fel az adatvezérelt teszteket:
-
Felderítési fázis: Az MSTest kiértékeli az összes adatforrásattribútumot (
DataRow,DynamicData, )ITestDataSourcea tesztelési esetek listájának meghatározásához. Ez a kiértékelés a normál MSTest életciklus-horgok futtatása előtt történik–AssemblyInitializeClassInitializeés más beállítási módszerek még nem hajthatóak végre. - Végrehajtási fázis: Az MSTest a normál életciklust futtatja (szerelvény inicializálása, osztály inicializálása, tesztelési inicializálás, tesztelési módszer, törlés), és minden tesztesetet végrehajt az adataival.
Mivel az adatforrások kiértékelése a felderítés során történik, az adatgeneráló kód nem támaszkodhat a `AssemblyInitialize` vagy a `ClassInitialize` által beállított állapotokra. Ha az adatforrás a beállítási logikától függ (például egy inicializált ClassInitializeadatbázis-kapcsolatból való olvasás), az adatforrás kiértékelése sikertelen lesz a felderítés során.
Elérhető stratégiák
| Stratégia | Magatartás |
|---|---|
Auto (alapértelmezett) |
Az MSTest határozza meg a legjobb kibontakozási stratégiát. |
Unfold |
Minden teszteset ki van bontva, és egyenként jelenik meg. |
Fold |
Minden teszteset egyetlen tesztcsomópontba van összecsukva. |
Összecsukott és ki nem bontott tesztek
A kibontási stratégia hatással van a teszteredmények jelentésére a Test Explorerben és a TRX-kimenetben:
- Kibontott tesztek: Minden adatsor külön, független tesztbejegyzésként jelenik meg a Test Explorerben és a TRX-ben. Az egyes teszteseteket futtathatja, hibakeresésre vagy szűrésre is használhatja. Minden bejegyzés saját pass/fail állapotú.
- Összecsukott tesztek: Minden adatsor egyetlen tesztcsomópontként jelenik meg a Test Explorerben. Egy bejegyzés jelenik meg a TRX-ben, amely több eredményt is társít az adott tesztesethez. Az egyes adatsorok egymástól függetlenül nem futtathatók és nem szűrhetők.
Kivétel a felderítés során összeomlást okoz
Ha az MSTest kiértékel egy adatforrást a felderítés során, és a kiértékelés kivételt eredményez, a teszt a konfigurált bontási stratégiától függetlenül visszaáll a hajtogatott állapotra. Mivel a keretrendszer nem tudja felsorolni az egyes teszteseteket, a tesztmetódus egyetlen (összecsukott) bejegyzésként van regisztrálva.
A végrehajtáskor az MSTest újra kiértékeli az adatforrást a normál életciklus részeként. Ha a kivételt hiányzó beállítási állapot (például egy ClassInitialize függőség) okozta, az adatforrás sikeres lehet a végrehajtás során, mert az életciklus-horgok már futnak.
Megjegyzés:
A felderítés során felmerülő teszt hibakeresése esetén kivétel (például a NullReferenceException) jelenhet meg a teszt megkezdése előtt. Ez a kivétel a felderítési fázis kiértékeléséből származik. Nyomja le a Continue billentyűt a hibakeresőben – a teszt ezután normálisan fut, mert a végrehajtási fázis a teljes MSTest-életciklust futtatja, beleértve az inicializálási módszereket is. További részletekért lásd: microsoft/testfx#7774.
Mikor kell módosítani a stratégiát?
A legtöbb forgatókönyv esetében az alapértelmezett Auto viselkedés biztosítja a legjobb egyensúlyt. Ha konkrét követelményekkel rendelkezik, fontolja meg a kibontási stratégia módosítását:
- Akkor használja
Fold, ha az adatforrások a futtatókörnyezet állapotától vagy a felderítés során nem elérhető beállítási logikától függnek. - Olyan nem determinisztikus adatforrásokhoz használható
Fold, amelyek különböző értékeket adnak vissza az egyes értékelésekhez. - Használja a
Fold-t a többletterhelés csökkentésére, ha a nagy számú teszteset teljesítménye aggodalomra ad okot.
Példa használatra
[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
}
}
Ajánlott eljárások
-
Válassza ki a megfelelő attribútumot: Egyszerű, beágyazott adatokhoz használható
DataRow. Összetett vagy számított adatokhoz használhatóDynamicData. -
Nevezze el a teszteseteket: A tesztelési hibák könnyebb azonosítására használható
DisplayName. - Az adatforrások közel tartása: Az adatforrások definiálása ugyanabban az osztályban, ha lehetséges, a jobb karbantarthatóság érdekében.
- Hasznos adatok használata: Válasszon ki olyan tesztadatokat, amelyek éles eseteket és határfeltételeket gyakorolnak.
- Fontolja meg a kombinatorikus tesztelést: A paraméterek kombinációinak teszteléséhez használja a Combinatorial.MSTest csomagot.