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.
MSTest poskytuje dobře definovaný životní cyklus pro testovací třídy a testovací metody, což umožňuje provádět operace nastavení a odstranění v různých fázích provádění testů. Pochopení životního cyklu pomáhá psát efektivní testy a vyhnout se běžným nástrahám.
Přehled životního cyklu
Životní cyklus seskupí do čtyř fází, které se provádějí od nejvyšší úrovně (sestavení) po nejnižší úroveň (testovací metoda):
- Úroveň sestavení: Spustí se jednou, když testovací sestavení načte a uvolní zatížení.
- Úroveň třídy: Spustí se jednou pro každou testovací třídu.
- Globální úroveň testu: Spustí se před a po každé testovací metodě v sestavení.
- Úroveň testu: Spustí se pro každou testovací metodu (včetně každého datového řádku v parametrizovaných testech).
Životní cyklus na úrovni sestavení
Metody životního cyklu sestavení se spustí jednou, když testovací sestavení načte a uvolní zatížení. Použijte je pro nákladné jednorázové nastavení, jako je inicializace databáze nebo spuštění služby.
AssemblyInitialize a AssemblyCleanup
[TestClass]
public class AssemblyLifecycleExample
{
private static IHost? _host;
[AssemblyInitialize]
public static async Task AssemblyInit(TestContext context)
{
// Runs once before any tests in the assembly
_host = await StartTestServerAsync();
context.WriteLine("Test server started");
}
[AssemblyCleanup]
public static async Task AssemblyCleanup(TestContext context)
{
// Runs once after all tests complete
// TestContext parameter available in MSTest 3.8+
if (_host != null)
{
await _host.StopAsync();
}
}
private static Task<IHost> StartTestServerAsync()
{
// Server initialization
return Task.FromResult<IHost>(null!);
}
}
Požadavky
- Metody musí být
public static - Návratový typ:
void,TaskneboValueTask(MSTest v3.3+) -
AssemblyInitializevyžaduje jeden parametr.TestContext -
AssemblyCleanuppřijímá nulové parametry nebo jedenTestContextparametr (MSTest 3.8+) - Pro každé sestavení je povolený pouze jeden atribut.
- Musí být ve třídě označené
[TestClass]
Návod
Související analyzátory:
-
MSTEST0012 – ověří
AssemblyInitializepodpis. -
MSTEST0013 – ověří
AssemblyCleanuppodpis.
Sdílené montážní přípravky s AssemblyFixtureProvider
Poznámka:
Tato AssemblyFixtureProviderAttribute verze byla zavedena v MSTest 4.3.0.
Ve výchozím nastavení musí být metody [AssemblyInitialize] a [AssemblyCleanup] deklarovány v testovacím sestavení, které je používá.
AssemblyFixtureProviderAttribute umožňuje deklarovat tyto metody jedinkrát ve sdílené knihovně a zajistit, aby byly rozpoznány a spuštěny jednou pro každé testovací sestavení, které ji používá. Použijte atribut na úrovni sestavení a nasměrujte ho na typ, který hostuje [AssemblyInitialize]/[AssemblyCleanup] metody.
// In a shared library.
public static class SharedAssemblyFixtures
{
[AssemblyInitialize]
public static void Init(TestContext context)
{
// Runs once per consuming test assembly.
}
[AssemblyCleanup]
public static void Cleanup()
{
}
}
// In each test assembly that should run the shared fixtures.
[assembly: AssemblyFixtureProvider(typeof(SharedAssemblyFixtures))]
Atribut umožňuje v rámci sestavení více poskytovatelů, takže můžete sestavovat fixture z několika sdílených typů.
Životní cyklus na úrovni třídy
Metody životního cyklu třídy se spouštějí jednou pro každou třídu testu před a po všech testovacích metodách v této třídě. Použijte je k nastavení sdílené napříč testy ve třídě.
ClassInitialize a ClassCleanup
[TestClass]
public class ClassLifecycleExample
{
private static HttpClient? _client;
[ClassInitialize]
public static void ClassInit(TestContext context)
{
// Runs once before any tests in this class
_client = new HttpClient
{
BaseAddress = new Uri("https://api.example.com")
};
}
[ClassCleanup]
public static void ClassCleanup()
{
// Runs after all tests in this class complete
_client?.Dispose();
}
[TestMethod]
public async Task GetUsers_ReturnsSuccess()
{
HttpResponseMessage response = await _client!.GetAsync("/users");
Assert.IsTrue(response.IsSuccessStatusCode);
}
}
Požadavky
- Metody musí být
public static - Návratový typ:
void,TaskneboValueTask(MSTest v3.3+) -
ClassInitializevyžaduje jeden parametr.TestContext -
ClassCleanuppřijímá nulové parametry nebo jedenTestContextparametr (MSTest 3.8+) - Pro každou třídu je povolený pouze jeden atribut.
Poznámka:
Od verze MSTest 4.2 hlásí MSTest selhání v ClassCleanup a AssemblyCleanup jako samostatné výsledky testů. Oddělený výsledek usnadňuje identifikaci selhání při čištění v Test Exploreru a sestavách TRX.
Chování dědičnosti
Určete, zda ClassInitialize se spouští pro odvozené třídy pomocí InheritanceBehavior:
[TestClass]
public class BaseTestClass
{
[ClassInitialize(InheritanceBehavior.BeforeEachDerivedClass)]
public static void BaseClassInit(TestContext context)
{
// Runs before each derived class's tests
}
}
[TestClass]
public class DerivedTestClass : BaseTestClass
{
[TestMethod]
public void DerivedTest()
{
// BaseClassInit runs before this class's tests
}
}
| Dědičnost chování | Description |
|---|---|
None (výchozí) |
Inicializace se spustí pouze pro deklarující třídu. |
BeforeEachDerivedClass |
Inicializace se provede před každou odvozenou třídou. |
Návod
Související analyzátory:
-
MSTEST0010 – ověří
ClassInitializepodpis. -
MSTEST0011 – ověří
ClassCleanuppodpis. -
MSTEST0034 - doporučuje používat
ClassCleanupBehavior.EndOfClass.
Globální životní cyklus na úrovni testu
Poznámka:
Atributy globálního životního cyklu testů byly zavedeny v MSTest 3.10.0.
Globální metody životního cyklu testů běží před a po každé testovací metodě v celém sestavení, aniž by bylo nutné do každé testovací třídy přidávat kód.
GlobalTestInitialize a GlobalTestCleanup
[TestClass]
public class GlobalTestLifecycleExample
{
[GlobalTestInitialize]
public static void GlobalTestInit(TestContext context)
{
// Runs before every test method in the assembly
context.WriteLine($"Starting test: {context.TestName}");
}
[GlobalTestCleanup]
public static void GlobalTestCleanup(TestContext context)
{
// Runs after every test method in the assembly
context.WriteLine($"Finished test: {context.TestName}");
}
}
Požadavky
- Metody musí být
public static - Návratový typ:
void,TaskneboValueTask - Musí mít přesně jeden parametr.
TestContext - Musí být ve třídě označené
[TestClass] - V sestavení je povoleno více metod s těmito atributy.
Poznámka:
Pokud existuje více metod GlobalTestInitialize nebo GlobalTestCleanup, není zaručeno pořadí jejich provádění. U TimeoutAttribute metod se nepodporuje GlobalTestInitialize .
Návod
Související analyzátor: MSTEST0050 – ověřuje globální metody zařízení testů.
Životní cyklus testu
Životní cyklus testovací úrovně běží pro každou testovací metodu. U parametrizovaných testů se životní cyklus spouští pro každý řádek dat.
Fáze nastavení
Použijte TestInitialize nebo konstruktor pro nastavení pro každý test:
[TestClass]
public class TestLevelSetupExample
{
private Calculator? _calculator;
public TestLevelSetupExample()
{
// Constructor runs before TestInitialize
// Use for simple synchronous initialization
}
[TestInitialize]
public async Task TestInit()
{
// Runs before each test method
// Supports async, attributes like Timeout
_calculator = new Calculator();
await _calculator.InitializeAsync();
}
[TestMethod]
public void Add_TwoNumbers_ReturnsSum()
{
int result = _calculator!.Add(2, 3);
Assert.AreEqual(5, result);
}
}
Konstruktor vs. TestInitialize:
| Aspekt | Konstruktor | TestInitialize |
|---|---|---|
| Podpora asynchronních operací | Ne | Ano |
| Podpora časového limitu | Ne | Ano (s atributem [Timeout] ) |
| Pořadí provádění | First | Po konstruktoru |
| Dědičnost | Základ pak odvozený | Základ pak odvozený |
| Chování výjimky | Vyčištění a odstranění se nespustí (neexistuje žádná instance) | Vyčištění a ukládání stále probíhají |
Návod
Jaký přístup mám použít? Konstruktory jsou obecně upřednostňované, protože umožňují používat readonly pole, která vynucují neměnnost a usnadňují zdůvodnění třídy testů. Použijte TestInitialize , když potřebujete podporu asynchronní inicializace nebo vypršení časového limitu.
Můžete také kombinovat oba přístupy: použít konstruktor pro jednoduchou synchronní inicializaci readonly polí a TestInitialize pro další asynchronní nastavení, které závisí na těchto polích.
Volitelně můžete povolit analyzátory kódu, aby vynutily konzistentní přístup:
- MSTEST0019 – Preferujte metody TestInitialize před konstruktory
- MSTEST0020 – Preferujte konstruktory před metodami TestInitialize
Fáze provádění
Testovací metoda se spustí po dokončení instalace. U async testovacích metod nástroj MSTest očekává vrácenou hodnotu Task nebo ValueTask.
Výstraha
Asynchronní testovací metody nemají SynchronizationContext ve výchozím nastavení. To se nevztahuje na UITestMethod testy v UPW a WinUI, které běží ve vlákně uživatelského rozhraní.
Fáze vyčištění
Použijte TestCleanup nebo IDisposable/IAsyncDisposable pro vyčištění po každém testu:
[TestClass]
public class TestLevelCleanupExample
{
private HttpClient? _client;
[TestInitialize]
public void TestInit()
{
_client = new HttpClient();
}
[TestCleanup]
public void TestCleanup()
{
if (_client != null)
{
_client.Dispose();
}
}
[TestMethod]
public async Task GetData_ReturnsSuccess()
{
HttpResponseMessage response = await _client!.GetAsync("https://example.com");
Assert.IsTrue(response.IsSuccessStatusCode);
}
}
Pořadí provádění vyčištění (odvozeno ze základu):
-
TestCleanup(odvozená třída) -
TestCleanup(základní třída) -
DisposeAsync(pokud je implementováno) -
Dispose(pokud je implementováno)
Návod
Volitelně můžete povolit analyzátory kódu, aby vynutily konzistentní přístup k vyčištění:
- MSTEST0021 – Preferujte Dispose před metodami TestCleanup
- MSTEST0022 – Preferujte testCleanup před metodami Dispose
Pokud máte povolené jiné analyzátory než MSTest, například .NET pravidla analýzy kódu, může se zobrazit CA1001, který navrhuje, abyste implementovali vzor pro uvolňování, pokud testovací třída vlastní uvolnitelné prostředky. Toto chování je očekávané a měli byste postupovat podle pokynů analyzátoru.
Dokončení pořadí v rámci testu
- Vytvoření instance testovací třídy (konstruktoru)
- Nastavit
TestContextvlastnost (pokud je k dispozici) - Spustit
GlobalTestInitializemetody - Spustit
TestInitializemetody (od základní k odvozené) - Provedení testovací metody
- Aktualizace
TestContexts výsledky (napříkladOutcomevlastnost) - Metody spuštění
TestCleanup(odvozené ze základu) - Spustit
GlobalTestCleanupmetody - Spusťte
DisposeAsync(pokud je implementováno) - Spusťte
Dispose(pokud je implementováno)
Návod
Související analyzátory:
-
MSTEST0008 – ověří
TestInitializepodpis. -
MSTEST0009 – ověří
TestCleanuppodpis. - MSTEST0063 – ověřuje konstruktor testovací třídy.
Osvědčené postupy
Použijte odpovídající obor: Umístěte nastavení na nejvyšší úroveň, která dává smysl vyhnout se redundantní práci.
Udržujte nastavení rychle: Dlouhotrvající nastavení má vliv na všechny testy. Zvažte línou inicializaci u náročných prostředků.
Správně vyčistěte: Vždy pečlivě uvolněte prostředky, k zabránění rušení testů a úniků paměti.
Správně zpracujte asynchronní operace: U asynchronních metod životního cyklu používejte
async Tasknávratové typy, neasync void.Zvažte izolaci testů: Každý test by měl být nezávislý. Vyhněte se sdílenému proměnlivému stavu mezi testy.
Používejte GlobalTest střídmě: Globální metody životního cyklu se spouštějí pro každý test, takže je udržujte jednoduché a lehké.