7

Ho pensato che lo scopo di questi attributi era di eseguirli una sola volta per assemblaggio. Ho una classe semplice come segue:Perché [AssemblyInitialize] e [AssemblyCleanup] vengono chiamati due volte nello stesso assembly del progetto di test?

[TestClass] 
public class AssemblyIntegrationTestSetup 
{ 
    public AssemblyIntegrationTestSetup() { } 
    public TestContext TestContext { get; set; } 

    [AssemblyInitialize] 
    public static void SetupIntegrationTests(TestContext context) 
    { 
     WindowsServiceService.Instance.StartService("Distributed Transaction Coordinator"); 
    } 

    [AssemblyCleanup] 
    public static void TeardownIntegrationTests() 
    { 
      WindowsServiceService.Instance.StopService("Distributed Transaction Coordinator"); 
    } 

} 

Tuttavia quando si esegue la suite di test il livello di assemblaggio di inizializzazione e metodi di pulizia eseguire due volte. Ecco i dettagli sul mio ambiente:

  1. Tutte le classi di test si trovano nello stesso progetto/assieme.
  2. I test di integrazione e unità sono separati da spazio dei nomi.
  3. Per i test di integrazione, sto utilizzando MSTextExtensions per consentire il rollback sulle transazioni del database.
  4. Sto anche avviando/fermando il servizio DTC MS SQL Server, che è richiesto per la capacità di rollback. Volevo farlo una volta per sessione di test (e il miglior compromesso che ho trovato è stato utilizzare gli attributi a livello di assembly). Il codice funzionerà, ma viene eseguito due volte.
  5. Se è importante, sto utilizzando anche Microsoft Moles Framework in alcuni dei miei test.

il comportamento osservato è simile a:

AssemblyInitialize   

Class1.TestInitialize 
Class1.TestMethod1 
Class1.TestCleanup 

AssemblyInitalize   <-- //This shouldn't be happening right? 

Class2.TestInitialize 
Class2.TestMethod1 
Class2.TestCleanup 

Class2.TestInitialize 
Class2.TestMethod2 
Class2.TestCleanup 

Class5.TestInitialize 
Class5.TestMethod1 
Class5.TestCleanup 

Class7.TestInitialize 
Class7.TestMethod1 
Class7.TestCleanup 

//More random bouncing around then... 

AssemblyCleanup 
AssemblyCleanup   <-- //This shouldn't be happening right? 

risposta

5

Dall'articolo MSDN Library:

Importante

Questo attributo non deve essere usato su ASP.NET unit test, ovvero qualsiasi test con attributo [HostType ("ASP.NET")] TE. A causa della natura senza stato di IIS e ASP.NET, un metodo decorato con questo attributo potrebbe essere chiamato più di una volta per esecuzione di test.


ci sono poche manopole quali si può giocare nella prova di corridore. Vorrei solo punt il problema con un contatore:

private int InitCount; 

[AssemblyInitialize] 
public static void SetupIntegrationTests(TestContext context) 
{ 
    if (InitCount++ == 0) { 
     WindowsServiceService.Instance.StartService("Distributed Transaction Coordinator"); 
    } 
} 

[AssemblyCleanup] 
public static void TeardownIntegrationTests() 
{ 
     if (--InitCount == 0) { 
      WindowsServiceService.Instance.StopService("Distributed Transaction Coordinator"); 
     } 
} 
+0

L'ho visto nella documentazione ma non sapevo se quella fosse la causa di sicuro. Ho un post separato nei forum Pex & Moles di MSDN riguardo l'attributo HostType: http://social.msdn.microsoft.com/Forums/en-US/pex/thread/b690442b-0333-42b8-928c-6f5f8bc44b02. Non sono convinto che sia il problema dal momento che quella nota riguarda ASP.NET e IIS. Inoltre, per quanto ne so, MS Moles non ti consente di aggiungere l'attributo HostType ai metodi AssemblyInitialize/Cleanup. Ma per quanto riguarda gli altri? Questo è quello che sto chiedendo lì. – Matt

+0

@Matt - post aggiornato. –

1

Bene, questa risposta è un anno bazillion in ritardo rispetto alla data di problema originale, ma ...

ho scoperto se l'agente di test (QTAgent32.exe) si blocca o muore prima che la sequenza completa termini, quindi AssemblyInitialize (e magari ClassInitialize e TestInitialize) verrebbero richiamati. Per esempio, mettere questo in funzione di [AssemblyCleanup] e vedrete verifica il comportamento:

Process p = AutotestShared.RunProcess("cmd", "/c taskkill /t /f /im QTAgent32.exe", true); 
p.WaitForExit(); 

Quindi la morale di questa storia è: Controllare le funzioni di pulizia per vedere se ci sono gli arresti/corruzione. Gli errori durante la pulizia non vengono visualizzati nel rapporto di test perché le asserzioni pass/fail sono già complete. Ma i problemi che provoca possono comparire in altri modi.

Problemi correlati