Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
MSTest fornisce attributi per controllare la modalità di esecuzione dei test, tra cui parallelizzazione, modelli di threading, timeout, tentativi ed esecuzione condizionale in base alla piattaforma o all'ambiente.
Attributi di threading
Gli attributi di threading controllano quali metodi di test del modello di thread usano. Questi attributi sono essenziali quando si testano componenti COM, elementi dell'interfaccia utente o codice con requisiti di threading specifici.
STATestClassAttribute
STATestClassAttribute esegue tutti i metodi di test in una classe (inclusi ClassInitialize e ClassCleanup) in un appartamento a thread singolo (STA). Usare questo attributo durante il test di oggetti COM che richiedono STA.
[STATestClass]
public class ComInteropTests
{
[TestMethod]
public void TestComComponent()
{
// This test runs in an STA thread
var comObject = new SomeComObject();
// Test COM interactions
}
}
Annotazioni
Questo attributo è supportato solo in Windows in MSTest v3.6 e versioni successive.
STATestMethodAttribute
STATestMethodAttribute Esegue un metodo di test specifico in un'appartamento a thread singolo. Usare questo attributo per i singoli test che necessitano di STA mentre altri test nella classe non lo sono.
[TestClass]
public class MixedThreadingTests
{
[STATestMethod]
public void TestRequiringSTA()
{
// This test runs in an STA thread
}
[TestMethod]
public void RegularTest()
{
// This test uses default threading
}
}
Annotazioni
Questo attributo è supportato solo in Windows in MSTest v3.6 e versioni successive.
Mantenere il contesto STA per le continuazioni asincrone
A partire da MSTest 4.1, STATestMethodAttribute include una UseSTASynchronizationContext proprietà che garantisce l'esecuzione delle continuazioni asincrone nello stesso thread STA. Se abilitato, l'attributo crea un oggetto personalizzato SynchronizationContext che restituisce le continuazioni al thread STA, ed è essenziale per il test dei componenti dell'interfaccia utente che richiedono il threading STA durante le operazioni asincrone.
[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);
}
}
Suggerimento
Usare UseSTASynchronizationContext = true quando si testano componenti Windows Form o WPF che eseguono operazioni asincrone e si prevede che le relative continuazioni vengano eseguite nello stesso thread.
UITestMethodAttribute
L'attributo UITestMethod pianifica l'esecuzione del test nel thread dell'interfaccia utente. Questo attributo è progettato per testare le applicazioni UWP e WinUI che richiedono l'accesso al thread dell'interfaccia utente.
[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);
}
}
Annotazioni
Questo attributo richiede l'adattatore MSTest appropriato per le piattaforme UWP o WinUI. Per altre informazioni, vedere la sezione supporto della piattaforma .
Attributi di parallelizzazione
Gli attributi di parallelizzazione controllano se e come i test vengono eseguiti simultaneamente, migliorando il tempo di esecuzione dei test.
ParallelizeAttribute
Per impostazione predefinita, MSTest esegue i test in sequenza. L'attributo a livello di assembly consente l'esecuzione ParallelizeAttribute di test paralleli.
using Microsoft.VisualStudio.TestTools.UnitTesting;
[assembly: Parallelize(Workers = 0, Scope = ExecutionScope.MethodLevel)]
Ambito di parallelizzazione
| Ambito | Comportamento |
|---|---|
ClassLevel |
Più classi di test vengono eseguite in parallelo, ma i test all'interno di una classe vengono eseguiti in sequenza |
MethodLevel |
I singoli metodi di test possono essere eseguiti in parallelo, indipendentemente dalla classe |
Thread di lavoro
La Workers proprietà specifica il numero massimo di thread per l'esecuzione parallela:
-
0(impostazione predefinita): usare il numero di processori logici nel computer - Qualsiasi numero intero positivo: usare il numero specifico di thread
// Parallelize at class level with 2 worker threads
[assembly: Parallelize(Workers = 2, Scope = ExecutionScope.ClassLevel)]
Suggerimento
È anche possibile configurare la parallelizzazione tramite runsettings o testconfig.json senza modificare il codice.
Suggerimento
Abilitare la parallelizzazione a livello di assembly per impostazione predefinita, anche se molti test richiedono attualmente l'esecuzione sequenziale. Questo approccio incoraggia la scrittura di nuovi test che supportano l'esecuzione parallela dall'inizio. Usare l'analizzatore MSTEST0001 per assicurarsi che ogni classe di test dichiari in modo esplicito la finalità di parallelizzazione, che impone di verificare se ogni classe supporta in modo sicuro l'esecuzione simultanea. Spesso, escludendo solo alcune classi o metodi con DoNotParallelize è sufficiente, consentendo la maggior parte dei test da eseguire in parallelo per un'esecuzione di test notevolmente più veloce.
DoNotParallelizeAttribute
DoNotParallelizeAttribute Impedisce l'esecuzione parallela per assembly, classi o metodi specifici. Usare questo attributo quando i test condividono lo stato o le risorse a cui non è possibile accedere in modo sicuro contemporaneamente.
[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
}
}
Annotazioni
È necessario DoNotParallelize solo quando è stata abilitata l'esecuzione parallela con l'attributo Parallelize .
Attributi di timeout
Gli attributi di timeout impediscono l'esecuzione illimitata dei test e consentono di identificare i problemi di prestazioni.
TimeoutAttribute
TimeoutAttribute specifica il tempo massimo, espresso in millisecondi, a cui può essere sottoposto un metodo di test o fixture. Se l'esecuzione supera questo tempo, il test ha esito negativo.
[TestClass]
public class TimeoutTests
{
[TestMethod]
[Timeout(5000)] // 5 seconds
public void TestWithTimeout()
{
// Test must complete within 5 seconds
}
}
Suggerimento
È possibile configurare un timeout di test globale tramite runsettings (TestTimeout) o testconfig.json (timeout.test) senza modificare il codice.
Applicare il timeout ai metodi di fixture
È anche possibile applicare timeout ai metodi di inizializzazione e pulizia:
[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
}
}
Suggerimento
Ogni metodo fixture che accetta un attributo [Timeout] ha un'impostazione di configurazione globale equivalente. Configurare i timeout globalmente tramite runsettings o testconfig.json usando impostazioni come TestInitializeTimeout, ClassInitializeTimeout, AssemblyInitializeTimeout, e le relative controparti di pulizia.
Annotazioni
Non è garantito che i timeout siano precisi. Il test viene interrotto dopo il passaggio del tempo specificato, ma l'annullamento effettivo potrebbe richiedere leggermente più tempo.
Annullamento cooperativo
Per impostazione predefinita, MSTest esegue il wrapping di ogni metodo di test temporizzato in un'attività o un thread separato. Quando viene raggiunto il timeout, il framework smette di osservare il test, ma l'attività sottostante continua a essere eseguita in background. Questo comportamento può causare problemi:
- Il metodo di test continua ad accedere alle risorse e modificare lo stato anche dopo il timeout.
- L'esecuzione in background può causare condizioni di gara che influiscono sui test successivi.
- Ogni metodo temporizzato comporta un sovraccarico aggiuntivo dal wrapper del task/thread.
A partire da MSTest 3.6, usare la CooperativeCancellation proprietà per evitare questi problemi. In modalità cooperativa, MSTest non incapsula il test in un'attività aggiuntiva. Al contrario, quando viene raggiunto il timeout, il framework segnala il token di annullamento. Il codice di test è responsabile del controllo regolare del token e della terminazione senza errori.
[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
}
}
}
Vantaggi dell'annullamento cooperativo:
- Riduzione del sovraccarico delle prestazioni (nessun wrapper aggiuntivo di task/thread per ogni test).
- Pulizia delle risorse perché il codice gestisce l'annullamento in modo esplicito.
- È in linea con i modelli di annullamento .NET standard.
- Comportamento deterministico evitando le race condition tra il codice di test e l'esecuzione in background non osservata.
Annotazioni
L'annullamento cooperativo richiede che il codice di test controlli regolarmente il token di annullamento. Se il codice non controlla il token, il test non viene effettivamente arrestato quando viene raggiunto il timeout.
Suggerimento
È possibile abilitare l'annullamento cooperativo a livello globale per tutti gli attributi di timeout tramite runsettings o testconfig.json anziché impostarlo singolarmente su ogni attributo.
Suggerimento
Analizzatori correlati:
- MSTEST0045 : consiglia di usare l'annullamento cooperativo per gli attributi di timeout.
Attributi di tentativo di ripetizione
Gli attributi di ripetizione dei tentativi consentono di gestire i test non riusciti automaticamente eseguendo nuovamente i test non riusciti.
RetryAttribute
Il RetryAttribute, introdotto in MSTest 3.8, riprova automaticamente i metodi di test che falliscono o vanno in timeout. Configura i tentativi di ripetizione massimi, il ritardo tra i tentativi e la strategia di backoff.
[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
}
}
Opzioni di configurazione
| Proprietà | Description | Predefinito |
|---|---|---|
MaxRetryAttempts |
Numero massimo di tentativi (di sola lettura, impostato tramite il costruttore) | Obbligatorio |
MillisecondsDelayBetweenRetries |
Ritardo di base tra tentativi (in ms) | 0 |
BackoffType |
Constant o Exponential ritardo |
Constant |
Annotazioni
Solo uno RetryAttribute può essere presente in un metodo di test. Non è possibile usare RetryAttribute nei metodi che non sono contrassegnati con TestMethod.
Suggerimento
Analizzatori correlati:
-
MSTEST0043 - consiglia di usare
RetryAttributesui metodi di test.
Implementazioni di tentativi personalizzati
Creare una logica di riprova personalizzata ereditando da RetryBaseAttribute:
public class CustomRetryAttribute : RetryBaseAttribute
{
private readonly int _maxRetries;
public CustomRetryAttribute(int maxRetries)
{
_maxRetries = maxRetries;
}
// Implement abstract members
// Add custom logic for retry conditions
}
Attributi di esecuzione condizionale
Gli attributi di esecuzione condizionale controllano se i test vengono eseguiti in base a condizioni specifiche, ad esempio il sistema operativo o l'ambiente CI.
ConditionBaseAttribute
ConditionBaseAttribute è la classe base astratta per l'esecuzione condizionale. MSTest offre diverse implementazioni predefinite.
Annotazioni
Per impostazione predefinita, gli attributi della condizione non vengono ereditati. L'applicazione a una classe di base non influisce sulle classi derivate. Gli attributi di condizione personalizzati possono eseguire l'override di questo comportamento ridefinendo AttributeUsage, ma non è consigliabile mantenere la coerenza con gli attributi della condizione predefinita.
Suggerimento
Analizzatori correlati:
- MSTEST0041 : consiglia di usare attributi basati su condizioni con classi di test.
OSConditionAttribute
Il componente OSConditionAttribute esegue o salta i test in base al sistema operativo. Utilizzare l'enumerazione dei flag OperatingSystems per specificare a quali sistemi operativi si applicano.
[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
}
}
Sistemi operativi supportati
| Sistema operativo | Description |
|---|---|
Windows |
Microsoft Windows |
Linux |
Distribuzioni Linux |
OSX |
macOS |
FreeBSD |
FreeBSD |
Combinare i sistemi operativi con l'operatore OR bit per bit (|).
Suggerimento
Analizzatori correlati:
-
MSTEST0061 : consiglia di usare l'attributo
OSConditionanziché i controlli di runtime.
CIConditionAttribute
L'oggetto CIConditionAttribute esegue o ignora i test in base al fatto che vengano eseguiti in un ambiente di integrazione continua.
[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
Ignora IgnoreAttribute in modo incondizionato una classe o un metodo di test. Facoltativamente, specificare un motivo per ignorare.
Suggerimento
Analizzatore correlato: MSTEST0015 - Il metodo di test non deve essere ignorato. Abilitare questo analizzatore per rilevare i test ignorati in modo permanente.
[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
}
Collegamento agli elementi di lavoro
Quando si ignorano i test a causa di problemi noti, usa WorkItemAttribute o GitHubWorkItemAttribute per tracciabilità.
[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
}
}
Procedure consigliate
Usare la parallelizzazione in modo saggio: abilitare la parallelizzazione per i test indipendenti, ma usare
DoNotParallelizeper i test che condividono lo stato.Impostare i timeout appropriati: scegliere timeout che consentono l'esecuzione normale ma intercettano i test bloccati. Considerare gli ambienti CI lenti.
Preferire l'annullamento cooperativo: Utilizzare l'annullamento cooperativo per evitare il sovraccarico dei task wrapper aggiuntivi e impedire l'esecuzione in background di test che hanno superato il tempo limite. Abilitare l'analizzatore MSTEST0045 per applicare questa procedura.
Test ignorati del documento: Si prega di fornire sempre un motivo e un riferimento al work item quando si ignorano i test.
Usare i tentativi con moderazione: risolvere la causa principale dei test instabili anziché basarsi sui tentativi.
Testare il codice specifico del sistema operativo in modo appropriato: usare
OSConditionper eseguire test specifici della piattaforma solo se sono applicabili.
Vedere anche
- Configurare MSTest
- Ciclo di vita dei test
- Scrivere test in MSTest
- MSTEST0001: Usare l'attributo Parallelize
- MSTEST0041: usare attributi basati su condizioni con la classe di test
- MSTEST0043: usare l'attributo di ripetizione dei tentativi nel metodo di test
- MSTEST0045: usare l'annullamento cooperativo per il timeout
- MSTEST0059: usare correttamente l'attributo Parallelize
- MSTEST0061: Usare l'attributo OSCondition anziché il controllo di runtime