Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Narzędzie MSTest udostępnia atrybuty do kontrolowania sposobu wykonywania testów, w tym przetwarzania równoległego, modeli wątków, limitów czasu, ponawiania prób i wykonywania warunkowego na podstawie platformy lub środowiska.
Atrybuty wątkowania
Atrybuty wątków kontrolują model wątku, którego używają metody testowe. Te atrybuty są niezbędne podczas testowania składników COM, elementów interfejsu użytkownika lub kodu z określonymi wymaganiami wątkowymi.
STATestClassAttribute
Urządzenie STATestClassAttribute uruchamia wszystkie metody testowe w klasie (w tym ClassInitialize i ClassCleanup) w mieszkaniu jednowątkowym (STA). Użyj tego atrybutu podczas testowania obiektów COM, które wymagają sta.
[STATestClass]
public class ComInteropTests
{
[TestMethod]
public void TestComComponent()
{
// This test runs in an STA thread
var comObject = new SomeComObject();
// Test COM interactions
}
}
Uwaga / Notatka
Ten atrybut jest obsługiwany tylko w systemie Windows w programie MSTest w wersji 3.6 lub nowszej.
STATestMethodAttribute
Uruchamia STATestMethodAttribute określoną metodę testową w jednym wątkowym mieszkaniu. Użyj tego atrybutu dla poszczególnych testów, które potrzebują STA, podczas gdy inne testy w tej klasie tego nie potrzebują.
[TestClass]
public class MixedThreadingTests
{
[STATestMethod]
public void TestRequiringSTA()
{
// This test runs in an STA thread
}
[TestMethod]
public void RegularTest()
{
// This test uses default threading
}
}
Uwaga / Notatka
Ten atrybut jest obsługiwany tylko w systemie Windows w programie MSTest w wersji 3.6 lub nowszej.
Zachowywanie kontekstu STA dla kontynuacji asynchronicznych
Począwszy od MSTest 4.1, element STATestMethodAttribute zawiera właściwość UseSTASynchronizationContext, która zapewnia, że kontynuacje asynchroniczne są uruchamiane w tym samym wątku STA. Po włączeniu atrybut tworzy niestandardowy SynchronizationContext element, który publikuje kontynuacje wątku STA, co jest niezbędne do testowania składników interfejsu użytkownika, które wymagają wątkowania STA w ramach operacji asynchronicznych.
[TestClass]
public class UIComponentTests
{
[STATestMethod(UseSTASynchronizationContext = true)]
public async Task TestAsyncUIOperation()
{
// Initial code runs on STA thread
var control = new MyControl();
await control.LoadDataAsync();
// Continuation also runs on STA thread,
// ensuring UI operations remain valid
Assert.IsTrue(control.IsDataLoaded);
}
}
Wskazówka
Użyj UseSTASynchronizationContext = true podczas testowania składników Windows Forms lub WPF, które wykonują operacje asynchroniczne i oczekują kontynuacji działania w tym samym wątku.
UITestMethodAttribute
Atrybut UITestMethod planuje wykonywanie testów w wątku interfejsu użytkownika. Ten atrybut jest przeznaczony do testowania aplikacji UWP i WinUI, które wymagają dostępu do wątku interfejsu użytkownika.
[TestClass]
public class WinUITests
{
[UITestMethod]
public void TestUIComponent()
{
// This test runs on the UI thread
var button = new Button();
button.Content = "Click me";
Assert.IsNotNull(button.Content);
}
}
Uwaga / Notatka
Ten atrybut wymaga odpowiedniego adaptera MSTest dla platform UWP lub WinUI. Aby uzyskać więcej informacji, zobacz sekcję pomocy technicznej platformy .
Atrybuty równoległościowe
Atrybuty przetwarzania równoległego określają, czy i jak testy są uruchamiane współbieżnie, poprawiając czas wykonywania testu.
ParallelizeAttribute
Domyślnie narzędzie MSTest uruchamia testy sekwencyjnie. Atrybut ParallelizeAttribute na poziomie zestawu umożliwia równoległe wykonywanie testów.
using Microsoft.VisualStudio.TestTools.UnitTesting;
[assembly: Parallelize(Workers = 0, Scope = ExecutionScope.MethodLevel)]
Zakres przetwarzania równoległego
| Scope | Zachowanie |
|---|---|
ClassLevel |
Wiele klas testowych jest uruchamianych równolegle, ale testy w obrębie klasy są uruchamiane sekwencyjnie. |
MethodLevel |
Poszczególne metody testowe mogą być uruchamiane równolegle, niezależnie od ich klasy |
Wątki robocze
Właściwość Workers określa maksymalną liczbę wątków do wykonywania równoległego:
-
0(ustawienie domyślne): użyj liczby procesorów logicznych na maszynie - Dowolna dodatnia liczba całkowita: użyj tej konkretnej liczby wątków
// Parallelize at class level with 2 worker threads
[assembly: Parallelize(Workers = 2, Scope = ExecutionScope.ClassLevel)]
Wskazówka
Można również skonfigurować równoległość za pomocą runsettings lub testconfig.json bez modyfikowania kodu.
Wskazówka
Domyślnie włącz równoległość na poziomie kompilacji, nawet jeśli wiele testów wymaga wykonywania sekwencyjnego. Takie podejście zachęca do pisania nowych testów, które obsługują wykonywanie równoległe od samego początku. Użyj analizatora MSTEST0001 , aby upewnić się, że każda klasa testowa jawnie deklaruje intencję równoległości, co wymusza sprawdzenie, czy każda klasa bezpiecznie obsługuje wykonywanie współbieżne. Często wykluczenie tylko kilku klas lub metod z DoNotParallelize jest wystarczające, dzięki czemu większość testów może być uruchamiana równolegle w celu znacznie szybszego wykonywania testów.
DoNotParallelizeAttribute
Funkcja DoNotParallelizeAttribute zapobiega równoległym wykonywaniu określonych zestawów, klas lub metod. Użyj tego atrybutu, gdy testy współdzielą stan lub zasoby, do których nie można bezpiecznie uzyskiwać dostępu współbieżnego.
[assembly: Parallelize(Scope = ExecutionScope.MethodLevel)]
[TestClass]
public class ParallelTests
{
[TestMethod]
public void CanRunInParallel()
{
// This test can run with others
}
}
[TestClass]
[DoNotParallelize]
public class SequentialTests
{
[TestMethod]
public void MustRunSequentially()
{
// This class's tests run sequentially
}
}
[TestClass]
public class MixedTests
{
[TestMethod]
public void CanRunInParallel()
{
// This test can run with others
}
[TestMethod]
[DoNotParallelize]
public void MustBeIsolated()
{
// This specific test doesn't run in parallel
}
}
Uwaga / Notatka
Wystarczy DoNotParallelize tylko wtedy, gdy włączono wykonywanie równoległe z atrybutem Parallelize .
Atrybuty limitu czasu
Atrybuty limitu czasu uniemożliwiają uruchamianie testów na czas nieokreślony i pomagają identyfikować problemy z wydajnością.
TimeoutAttribute
Parametr TimeoutAttribute określa maksymalny czas (w milisekundach), który może uruchomić metoda testu lub urządzenia. Jeśli wykonanie przekroczy ten czas, test zakończy się niepowodzeniem.
[TestClass]
public class TimeoutTests
{
[TestMethod]
[Timeout(5000)] // 5 seconds
public void TestWithTimeout()
{
// Test must complete within 5 seconds
}
}
Wskazówka
Możesz skonfigurować globalny limit czasu testu za pomocą ustawień runsettings (TestTimeout) lub testconfig.json (timeout.test) bez modyfikowania kodu.
Zastosowanie limitu czasu do metod pomocniczych
Limity czasu można również zastosować do metod inicjalizacji i czyszczenia.
[TestClass]
public class FixtureTimeoutTests
{
[ClassInitialize]
[Timeout(10000)]
public static void ClassInit(TestContext context)
{
// Must complete within 10 seconds
}
[TestInitialize]
[Timeout(2000)]
public void TestInit()
{
// Must complete within 2 seconds
}
}
Wskazówka
Każda metoda fixture'a, która akceptuje atrybut [Timeout], ma równoważne globalne ustawienie konfiguracji. Skonfiguruj globalnie czas oczekiwania za pomocą runsettings lub testconfig.json przy użyciu ustawień, takich jak TestInitializeTimeout, ClassInitializeTimeout, AssemblyInitializeTimeout, i ich odpowiedniki oczyszczania.
Uwaga / Notatka
Czasowe limity nie gwarantują precyzyjności. Test przerywa się po upływie określonego czasu, ale rzeczywiste anulowanie może potrwać nieco dłużej.
Anulowanie współpracy
Domyślnie narzędzie MSTest umieszcza każdą metodę testową w osobnym zadaniu lub wątku. Po osiągnięciu limitu czasu struktura przestaje obserwować test, ale bazowe zadanie będzie nadal działać w tle. To zachowanie może powodować problemy:
- Metoda testowa nadal uzyskuje dostęp do zasobów i zmienia stan nawet po przekroczeniu limitu czasu.
- Wykonywanie w tle może prowadzić do warunków wyścigu wpływających na kolejne testy.
- Każda metoda czasowa wiąże się z dodatkowym narzutem związanym z opakowaniem zadań lub wątków.
Począwszy od msTest 3.6, użyj CooperativeCancellation właściwości , aby uniknąć tych problemów. W trybie kooperacyjnym narzędzie MSTest nie zawija testu w dodatkowe zadanie. Zamiast tego po osiągnięciu limitu czasu platforma sygnalizuje token anulowania. Kod testowy jest odpowiedzialny za regularne sprawdzanie tokenu i łagodne zakończenie działania.
[TestClass]
public class CooperativeTimeoutTests
{
[TestMethod]
[Timeout(5000, CooperativeCancellation = true)]
public async Task TestWithCooperativeCancellation(CancellationToken cancellationToken)
{
// Check the token periodically
while (!cancellationToken.IsCancellationRequested)
{
await Task.Delay(100, cancellationToken);
// Do work
}
}
[TestMethod]
[Timeout(5000, CooperativeCancellation = true)]
public void SyncTestWithCooperativeCancellation(CancellationToken cancellationToken)
{
// Works with sync methods too
for (int i = 0; i < 1000; i++)
{
cancellationToken.ThrowIfCancellationRequested();
// Do work
}
}
}
Korzyści wynikające z anulowania współpracy:
- Mniejsze obciążenie wydajności (bez dodatkowej nakładki zadań/wątków na test).
- Skuteczniejsze czyszczenie zasobów, ponieważ kod jawnie obsługuje anulowanie.
- Jest zgodny ze standardowymi wzorcami anulowania platformy .NET.
- Zachowanie deterministyczne dzięki unikaniu warunków wyścigu między kodem testowym a nieobserwowanym wykonywaniem w tle.
Uwaga / Notatka
Współpracujące anulowanie wymaga, aby kod testowy regularnie sprawdzał token anulowania. Jeśli kod nie sprawdzi tokenu, test nie zostanie zatrzymany po osiągnięciu limitu czasu.
Wskazówka
Możesz włączyć globalne anulowanie współpracy dla wszystkich atrybutów limitu czasu za pomocą ustawień uruchamiania lub testconfig.json zamiast ustawiać je osobno dla każdego atrybutu.
Wskazówka
Powiązane analizatory:
- MSTEST0045 — zaleca użycie anulowania kooperacyjnego dla atrybutów określających limit czasu.
Atrybuty ponawiania próby
Atrybuty ponawiania prób pomagają w obsłudze flakujących testów przez automatyczne ponowne uruchamianie testów, które zakończyły się niepowodzeniem.
RetryAttribute
Metoda RetryAttribute, wprowadzona w MSTest 3.8, automatycznie ponawia próby metod testowych, które kończą się niepowodzeniem lub przekroczeniem limitu czasu. Skonfiguruj maksymalną liczbę ponownych prób, opóźnienie między ponownymi próbami i strategię wycofywania.
[TestClass]
public class RetryTests
{
[TestMethod]
[Retry(3)] // Retry up to 3 times if the test fails
public void FlakeyNetworkTest()
{
// Test that might occasionally fail due to network issues
}
[TestMethod]
[Retry(3, MillisecondsDelayBetweenRetries = 1000, BackoffType = DelayBackoffType.Exponential)]
public void TestWithExponentialBackoff()
{
// Retries with increasing delays: 1s, 2s, 4s
}
[TestMethod]
[Retry(5, MillisecondsDelayBetweenRetries = 500, BackoffType = DelayBackoffType.Constant)]
public void TestWithConstantDelay()
{
// Retries with constant 500ms delay between attempts
}
}
Opcje konfiguracji
| Majątek | Description | Default |
|---|---|---|
MaxRetryAttempts |
Maksymalna liczba ponownych prób (tylko do odczytu, ustawiona za pomocą konstruktora) | Required |
MillisecondsDelayBetweenRetries |
Opóźnienie bazowe między ponownymi próbami (w ms) | 0 |
BackoffType |
Constant lub Exponential opóźnienie |
Constant |
Uwaga / Notatka
Tylko jeden RetryAttribute może być obecny w metodzie testowej. Nie można stosować RetryAttribute do metod, które nie są oznaczone słowem kluczowym TestMethod.
Niestandardowe implementacje ponawiania prób
Utwórz niestandardową logikę ponawiania, dziedzicząc z RetryBaseAttribute:
public class CustomRetryAttribute : RetryBaseAttribute
{
private readonly int _maxRetries;
public CustomRetryAttribute(int maxRetries)
{
_maxRetries = maxRetries;
}
// Implement abstract members
// Add custom logic for retry conditions
}
Atrybuty wykonywania warunkowego
Atrybuty warunkowego wykonywania określają, czy testy mają być uruchomione na podstawie określonych warunków, takich jak system operacyjny czy środowisko CI.
ConditionBaseAttribute
Jest ConditionBaseAttribute to abstrakcyjna klasa bazowa do wykonywania warunkowego. Narzędzie MSTest udostępnia kilka wbudowanych implementacji.
Uwaga / Notatka
Domyślnie atrybuty warunku nie są dziedziczone. Zastosowanie ich do klasy bazowej nie ma wpływu na klasy pochodne. Atrybuty warunku niestandardowego mogą zastąpić to zachowanie przez ponowne zdefiniowanie AttributeUsage, ale nie jest to zalecane, aby zachować spójność z wbudowanymi atrybutami warunku.
Wskazówka
Powiązane analizatory:
- MSTEST0041 — zaleca używanie atrybutów opartych na warunku z klasami testowymi.
OSConditionAttribute
Uruchamia lub pomija testy OSConditionAttribute na podstawie systemu operacyjnego. Użyj wyliczenia OperatingSystems flag, aby określić, które systemy operacyjne mają zastosowanie.
[TestClass]
public class OSSpecificTests
{
[TestMethod]
[OSCondition(OperatingSystems.Windows)]
public void WindowsOnlyTest()
{
// Runs only on Windows
}
[TestMethod]
[OSCondition(OperatingSystems.Linux | OperatingSystems.OSX)]
public void UnixLikeOnlyTest()
{
// Runs on Linux or macOS
}
[TestMethod]
[OSCondition(ConditionMode.Exclude, OperatingSystems.Windows)]
public void SkipOnWindowsTest()
{
// Runs on any OS except Windows
}
}
Obsługiwane systemy operacyjne
| System operacyjny | Description |
|---|---|
Windows |
Microsoft Windows |
Linux |
Dystrybucje systemu Linux |
OSX |
macOS |
FreeBSD |
FreeBSD |
Łączenie systemów operacyjnych z operatorem bitowym OR (|).
Wskazówka
Powiązane analizatory:
-
MSTEST0061 — zaleca użycie
OSConditionatrybutu zamiast kontroli środowiska uruchomieniowego.
CIConditionAttribute
Uruchamia CIConditionAttribute lub pomija testy na podstawie tego, czy są wykonywane w ramach środowiska ciągłej integracji.
[TestClass]
public class CIAwareTests
{
[TestMethod]
[CICondition] // Default: runs only in CI
public void CIOnlyTest()
{
// Runs only in CI environments
}
[TestMethod]
[CICondition(ConditionMode.Include)]
public void ExplicitCIOnlyTest()
{
// Same as above, explicitly stated
}
[TestMethod]
[CICondition(ConditionMode.Exclude)]
public void LocalDevelopmentOnlyTest()
{
// Skipped in CI, runs during local development
}
}
IgnoreAttribute
Bezwarunkowo IgnoreAttribute pomija klasę testową lub metodę. Opcjonalnie podaj przyczynę ignorowania.
Wskazówka
Powiązany analizator: MSTEST0015 — metoda testowa nie powinna być ignorowana. Włącz ten analizator, aby wykrywać testy, które są trwale ignorowane.
[TestClass]
public class IgnoreExamples
{
[TestMethod]
[Ignore]
public void TemporarilyDisabled()
{
// This test is skipped
}
[TestMethod]
[Ignore("Waiting for bug #123 to be fixed")]
public void DisabledWithReason()
{
// This test is skipped with a documented reason
}
}
[TestClass]
[Ignore("Entire class needs refactoring")]
public class IgnoredTestClass
{
[TestMethod]
public void Test1() { } // Skipped
[TestMethod]
public void Test2() { } // Skipped
}
Łącze do zadań roboczych
Podczas ignorowania testów ze względu na znane problemy użyj polecenia WorkItemAttribute lub GitHubWorkItemAttribute w celu śledzenia:
[TestClass]
public class TrackedIgnoreExamples
{
[TestMethod]
[Ignore("Waiting for fix")]
[WorkItem(12345)]
public void TestWithWorkItem()
{
// Linked to work item 12345
}
[TestMethod]
[Ignore("Known issue")]
[GitHubWorkItem("https://github.com/owner/repo/issues/42")]
public void TestWithGitHubIssue()
{
// Linked to GitHub issue #42
}
}
Najlepsze rozwiązania
Używaj równoległości mądrze: włącz równoległość dla niezależnych testów, ale użyj
DoNotParallelizedo testów, które współdzielą stan.Ustaw odpowiednie limity czasu: wybierz limity czasu, które umożliwiają normalne wykonanie, ale wykrywają zablokowane testy. Rozważ powolne środowiska ciągłej integracji.
Preferuj anulowanie kooperacyjne: używaj anulowania kooperacyjnego, aby uniknąć narzutu nadmiarowych opakowań zadań i zapobiec wykonywaniu testów przekraczających czas w tle. Włącz analizator MSTEST0045 , aby wymusić tę praktykę.
Dokumentowanie ignorowanych testów: zawsze podaj przyczynę i odniesienie do elementu roboczego podczas ignorowania testów.
Użyj ponownych prób oszczędnie: rozwiąż główną przyczynę niestabilnych testów, a nie polegaj na ponownych próbach.
Odpowiednio przetestuj kod specyficzny dla systemu operacyjnego: użyj polecenia
OSCondition, aby uruchamiać testy specyficzne dla platformy tylko wtedy, gdy mają zastosowanie.
Zobacz także
- Konfigurowanie narzędzia MSTest
- Cykl życia testu
- Pisanie testów w narzędziu MSTest
- MSTEST0001: Użyj atrybutu Parallelize
- MSTEST0041: Użyj atrybutów opartych na warunkach z klasą testową
- MSTEST0043: użyj atrybutu ponawiania próby w metodzie testowej
- MSTEST0045: Użyj anulowania kooperacyjnego w przypadku limitu czasu
- MSTEST0059: poprawnie użyj atrybutu Parallelize
- MSTEST0061: użyj atrybutu OSCondition zamiast sprawdzania środowiska uruchomieniowego