Remarque
L’accès à cette page requiert une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page requiert une autorisation. Vous pouvez essayer de modifier des répertoires.
MSTest fournit des attributs pour contrôler la façon dont les tests s’exécutent, notamment la parallélisation, les modèles de thread, les délais d’expiration, les nouvelles tentatives et l’exécution conditionnelle en fonction de la plateforme ou de l’environnement.
Attributs de thread
Les attributs de thread contrôlent le modèle de fil d'exécution utilisé par les méthodes de test. Ces attributs sont essentiels lors du test des composants COM, des éléments d’interface utilisateur ou du code avec des exigences de thread spécifiques.
STATestClassAttribute
Toutes les méthodes de test d'une classe (y compris STATestClassAttribute et ClassInitialize) s'exécutent dans un appartement à un seul thread (STA). Utilisez cet attribut lors du test des objets COM qui nécessitent STA.
[STATestClass]
public class ComInteropTests
{
[TestMethod]
public void TestComComponent()
{
// This test runs in an STA thread
var comObject = new SomeComObject();
// Test COM interactions
}
}
Note
Cet attribut est uniquement pris en charge sur Windows dans MSTest v3.6 et versions ultérieures.
STATestMethodAttribute
STATestMethodAttribute exécute une méthode de test spécifique dans un appartement à thread unique. Utilisez cet attribut pour les tests individuels qui ont besoin de STA alors que d’autres tests de la classe ne le font pas.
[TestClass]
public class MixedThreadingTests
{
[STATestMethod]
public void TestRequiringSTA()
{
// This test runs in an STA thread
}
[TestMethod]
public void RegularTest()
{
// This test uses default threading
}
}
Note
Cet attribut est uniquement pris en charge sur Windows dans MSTest v3.6 et versions ultérieures.
Conserver le contexte STA pour les continuations asynchrones
À compter de MSTest 4.1, la STATestMethodAttribute propriété inclut une UseSTASynchronizationContext propriété qui garantit l’exécution des continuations asynchrones sur le même thread STA. Lorsqu’il est activé, l’attribut crée un code personnalisé SynchronizationContext qui publie des continuations vers le thread STA, qui est essentiel pour tester les composants de l’interface utilisateur qui nécessitent un thread STA tout au long de leurs opérations asynchrones.
[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);
}
}
Conseil / Astuce
Utilisez cette option UseSTASynchronizationContext = true lors du test des composants Windows Forms ou WPF qui effectuent des opérations asynchrones et attendent que leurs continuations s’exécutent sur le même thread.
UITestMethodAttribute
L’attribut UITestMethod planifie l’exécution des tests sur le thread d’interface utilisateur. Cet attribut est conçu pour tester les applications UWP et WinUI qui nécessitent un accès au thread d’interface utilisateur.
[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);
}
}
Note
Cet attribut nécessite l’adaptateur MSTest approprié pour les plateformes UWP ou WinUI. Pour plus d’informations, consultez la section prise en charge de la plateforme.
Attributs de parallélisation
Les attributs de parallélisation contrôlent si et comment les tests s’exécutent simultanément, ce qui améliore le temps d’exécution des tests.
ParallelizeAttribute
Par défaut, MSTest exécute des tests séquentiellement. L’attribut au niveau de l’assembly ParallelizeAttribute active l’exécution de test parallèle.
using Microsoft.VisualStudio.TestTools.UnitTesting;
[assembly: Parallelize(Workers = 0, Scope = ExecutionScope.MethodLevel)]
Étendue de parallélisation
| Scope | Comportement |
|---|---|
ClassLevel |
Plusieurs classes de test s’exécutent en parallèle, mais les tests au sein d’une classe s’exécutent de manière séquentielle |
MethodLevel |
Les méthodes de test individuelles peuvent s’exécuter en parallèle, quelle que soit leur classe |
Threads de travail
La Workers propriété spécifie le nombre maximal de threads pour l’exécution parallèle :
-
0(par défaut) : utiliser le nombre de processeurs logiques sur l’ordinateur - Nombre entier positif : utilisez ce nombre de threads spécifiques
// Parallelize at class level with 2 worker threads
[assembly: Parallelize(Workers = 2, Scope = ExecutionScope.ClassLevel)]
Conseil / Astuce
Vous pouvez également configurer la parallélisation par le biais de runsettings ou detestconfig.json sans modifier le code.
Conseil / Astuce
Activez la parallélisation au niveau de l’assembly par défaut, même si de nombreux tests nécessitent actuellement une exécution séquentielle. Cette approche encourage l’écriture de nouveaux tests qui prennent en charge l’exécution parallèle à partir du début. Utilisez l’analyseur MSTEST0001 pour vous assurer que l’assembly déclare explicitement son intention de parallélisation avec [assembly: Parallelize] ou [assembly: DoNotParallelize]. Une fois la parallélisation activée, passez en revue chaque classe de test pour déterminer si elle prend en charge l’exécution simultanée en toute sécurité. Souvent, l’exclusion de quelques classes ou méthodes DoNotParallelize est suffisante, ce qui permet à la majorité de vos tests de s’exécuter en parallèle pour accélérer considérablement l’exécution des tests.
DoNotParallelizeAttribute
Le DoNotParallelizeAttribute empêche l’exécution parallèle pour des assemblies, classes ou méthodes spécifiques. Utilisez cet attribut lorsque les tests partagent l’état ou les ressources qui ne peuvent pas être accessibles en toute sécurité simultanément.
[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
}
}
Note
Vous n’avez besoin DoNotParallelize que lorsque vous avez activé l’exécution parallèle avec l’attribut Parallelize .
Attributs de délai d’expiration
Les attributs de délai d’attente empêchent l’exécution indéfinie des tests et aident à identifier les problèmes de performances.
TimeoutAttribute
Spécifie TimeoutAttribute la durée maximale (en millisecondes) qu’une méthode de test ou de montage peut exécuter. Si l’exécution dépasse cette période, le test échoue.
[TestClass]
public class TimeoutTests
{
[TestMethod]
[Timeout(5000)] // 5 seconds
public void TestWithTimeout()
{
// Test must complete within 5 seconds
}
}
Conseil / Astuce
Vous pouvez configurer un délai d’expiration de test global par le biais de runsettings (TestTimeout) ou detestconfig.json (timeout.test) sans modifier de code.
Appliquer le délai d’expiration aux méthodes de montage
Vous pouvez également appliquer des délais d’expiration aux méthodes d’initialisation et de nettoyage :
[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
}
}
Conseil / Astuce
Chaque méthode de montage qui accepte un [Timeout] attribut a un paramètre de configuration global équivalent. Configurez les délais d’expiration globalement par runsettings ou detestconfig.json à l’aide de paramètres tels que TestInitializeTimeout, ClassInitializeTimeout, AssemblyInitializeTimeout et leurs équivalents de nettoyage.
Note
Les délais d'expiration ne sont pas garantis d'être précisément exacts. Le test abandonne une fois que le temps spécifié passe, mais l’annulation réelle peut prendre un peu plus de temps.
Annulation coopérative
Par défaut, MSTest encapsule chaque méthode de test chronométrée dans une tâche ou un thread distinct. Lorsque le délai d’expiration est atteint, l’infrastructure cesse d’observer le test, mais la tâche sous-jacente continue de s’exécuter en arrière-plan. Ce comportement peut entraîner des problèmes :
- La méthode de test continue d’accéder aux ressources et de muter l’état même après le délai d’expiration.
- L’exécution en arrière-plan peut entraîner des conditions de course affectant les tests suivants.
- Chaque méthode chronométrée entraîne une surcharge supplémentaire due à l'enveloppe de tâche/thread.
À compter de MSTest 3.6, utilisez la CooperativeCancellation propriété pour éviter ces problèmes. En mode coopératif, MSTest n’encapsule pas votre test dans une tâche supplémentaire. Au lieu de cela, lorsque le délai d’expiration est atteint, le cadre signale le jeton d’annulation. Votre code de test est chargé de vérifier régulièrement le jeton et de terminer correctement.
[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
}
}
}
Avantages de l’annulation coopérative :
- Réduction de la surcharge de charge de travail (aucune enveloppe de tâche ou de fil d'exécution supplémentaire par test).
- Nettoyage des ressources plus propre, car votre code gère explicitement l’annulation.
- S’aligne sur les modèles d’annulation .NET standard.
- Comportement déterministe en évitant les conditions de course entre le code de test et l'exécution en arrière-plan non observée.
Note
L’annulation coopérative nécessite que votre code de test vérifie régulièrement le jeton d’annulation. Si votre code ne vérifie pas le jeton, le test ne s’arrête pas réellement lorsque le délai d’expiration est atteint.
Conseil / Astuce
Vous pouvez activer l’annulation coopérative globalement pour tous les attributs de délai d’expiration par le biais de runsettings ou detestconfig.json au lieu de le définir individuellement sur chaque attribut.
Conseil / Astuce
Analyseurs associés :
- MSTEST0045 : recommande d’utiliser l’annulation coopérative pour les attributs de délai d’expiration.
Attributs de nouvelle tentative
Les attributs de nouvelle tentative permettent de gérer les tests flaky en réexécutant automatiquement les tests ayant échoué.
RetryAttribute
Introduit dans MSTest 3.8, le RetryAttribute retente automatiquement les méthodes de test qui échouent ou expirent. Configurez le nombre maximal de tentatives, le délai entre celles-ci et la stratégie de recul.
[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
}
}
Options de configuration
| Propriété | Descriptif | Par défaut |
|---|---|---|
MaxRetryAttempts |
Nombre maximal de tentatives de nouvelle tentative (lecture seule, définie via le constructeur) | Obligatoire |
MillisecondsDelayBetweenRetries |
Délai de base entre les nouvelles tentatives (en ms) | 0 |
BackoffType |
Constant ou Exponential délai |
Constant |
Note
Un seul RetryAttribute peut être présent sur une méthode de test. Vous ne pouvez pas utiliser RetryAttribute sur les méthodes qui ne sont pas marquées avec TestMethod.
Conseil / Astuce
Analyseurs associés :
-
MSTEST0043 : recommande d’utiliser
RetryAttributesur les méthodes de test.
Implémentations de retries personnalisées
Créez une logique de nouvelle tentative personnalisée en hériter de RetryBaseAttribute:
public class CustomRetryAttribute : RetryBaseAttribute
{
private readonly int _maxRetries;
public CustomRetryAttribute(int maxRetries)
{
_maxRetries = maxRetries;
}
// Implement abstract members
// Add custom logic for retry conditions
}
Attributs d’exécution conditionnelle
Les attributs d’exécution conditionnelle contrôlent si les tests s’exécutent en fonction de conditions spécifiques telles que le système d’exploitation ou l’environnement CI.
ConditionBaseAttribute
Il ConditionBaseAttribute s’agit de la classe de base abstraite pour l’exécution conditionnelle. MSTest fournit plusieurs implémentations intégrées.
Note
Par défaut, les attributs de condition ne sont pas hérités. L’application de ces classes à une classe de base n’affecte pas les classes dérivées. Les attributs de condition personnalisée peuvent remplacer ce comportement en redéfinissant AttributeUsage, mais il n’est pas recommandé de maintenir la cohérence avec les attributs de condition intégrés.
Conseil / Astuce
Analyseurs associés :
- MSTEST0041 : recommande d’utiliser des attributs basés sur des conditions avec des classes de test.
OSConditionAttribute
Les OSConditionAttribute exécutent ou ignorent les tests en fonction du système d’exploitation. Utilisez l’énumération OperatingSystems des indicateurs pour spécifier les systèmes d’exploitation qui s’appliquent.
[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
}
}
Systèmes d'exploitation pris en charge
| Système d'exploitation | Descriptif |
|---|---|
Windows |
Microsoft Windows |
Linux |
Distributions Linux |
OSX |
macOS |
FreeBSD |
FreeBSD |
Combinez des systèmes d’exploitation avec l’opérateur OR au niveau du bit (|).
Conseil / Astuce
Analyseurs associés :
-
MSTEST0061 : recommande d’utiliser l’attribut
OSConditionau lieu de vérifications d’exécution.
CIConditionAttribute
Les CIConditionAttribute exécutent ou ignorent les tests selon qu'ils s'exécutent dans un environnement d’intégration continue.
[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
L’objet IgnoreAttribute ignore inconditionnellement une classe de test ou une méthode. Si vous le souhaitez, fournissez une raison d’ignorer.
Conseil / Astuce
Analyseur associé : MSTEST0015 - La méthode de test ne doit pas être ignorée. Activez cet analyseur pour détecter les tests qui sont ignorés définitivement.
[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
}
Lien vers des éléments de travail
Lorsque vous ignorez les tests en raison de problèmes connus, utilisez WorkItemAttribute ou GitHubWorkItemAttribute pour la traçabilité :
[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
}
}
Meilleures pratiques
Utilisez la parallélisation judicieusement : activez la parallélisation pour les tests indépendants, mais utilisez-la
DoNotParallelizepour les tests qui partagent l’état.Définir les délais d’expiration appropriés : choisissez les délais d’expiration qui autorisent l’exécution normale, mais interceptent les tests bloqués. Envisagez d’utiliser des environnements CI lents.
Privilégiez l’annulation coopérative : utilisez l’annulation coopérative afin d'éviter la surcharge des wrappers de tâches supplémentaires et empêcher l’exécution en arrière-plan des tests qui ont expiré. Activez l’analyseur MSTEST0045 pour appliquer cette pratique.
Déclaration des tests ignorés : fournissez toujours une raison et une référence à l'élément de travail lorsque vous ignorez les tests.
Utilisez les tentatives supplémentaires avec parcimonie : résolvez la cause première des tests instables plutôt que de vous appuyer sur les tentatives supplémentaires.
Testez le code propre au système d’exploitation de manière appropriée : utilisez-le
OSConditionpour exécuter des tests spécifiques à la plateforme uniquement lorsqu’ils sont applicables.
Voir aussi
- Configurer MSTest
- Cycle de vie des tests
- Écrire des tests dans MSTest
- MSTEST0001 : utiliser l’attribut Parallelize
- MSTEST0041 : utiliser des attributs basés sur des conditions avec une classe de test
- MSTEST0043 : Utiliser l’attribut nouvelle tentative sur la méthode de test
- MSTEST0045 : Utiliser l’annulation coopérative pour le délai d’expiration
- MSTEST0059 : utiliser l’attribut Parallelize correctement
- MSTEST0061 : Utiliser l’attribut OSCondition au lieu de la vérification du runtime