2012-01-07 12 views
5

Sto utilizzando WatiN per alcuni test automatici e quello che ho scoperto è stato che la creazione di un'istanza di IE per ogni test non era scalabile. L'ora di creazione e lo spegnimento di ogni istanza IE mi stava mangiando vivo:Come posso garantire che dispongo di un oggetto nel mio singleton prima che l'applicazione si chiuda?

[TestMethod] 
    public void Verify_Some_Useful_Thing() 
    { 
     using (var browser = new IE()) 
     { 
      browser.GoTo("/someurl"); 
      // etc.. 
      // some assert() statements 
     } 
    } 

Tuttavia, l'istruzione using ha dimostrato utile in quanto posso sempre garantire che il mio esempio IE avrebbe il suo metodo dispose() chiamato, che avrebbe chiuso la finestra di IE.

In ogni caso, ho creato un Singleton, che ha mantenuto una singola istanza di IE che tutti i miei test usano in tutte le mie classi di test:

public class BrowserPool 
{  
    private static readonly Lazy<BrowserPool> _instance = new Lazy<BrowserPool>(() => new BrowserPool());   

    private IE _browser; 
    private string _ieHwnd; 
    private int _threadId; 

    public IE Browser 
    { 
     get 
     { 
      var currentThreadId = GetCurrentThreadId(); 
      if (currentThreadId != _threadId) 
      { 
       _browser = IE.AttachTo<IE>(Find.By("hwnd", _ieHwnd)); 
       _threadId = currentThreadId; 
      } 
      return _browser; 
     } 
     set 
     { 
      _browser = value; 
      _ieHwnd = _browser.hWnd.ToString(); 
      _threadId = GetCurrentThreadId(); 
     } 
    } 

    /// <summary> 
    /// private to prevent direct instantiation. 
    /// </summary> 
    private BrowserPool() 
    { 
     Browser = new IE(); 
    } 

    /// <summary> 
    /// Get the current executing thread's id. 
    /// </summary> 
    /// <returns>Thread Id.</returns> 
    private int GetCurrentThreadId() 
    { 
     return Thread.CurrentThread.GetHashCode(); 
    } 

    /// <summary> 
    /// Accessor for instance 
    /// </summary> 
    public static BrowserPool Instance 
    { 
     get 
     { 
      return _instance; 
     } 
    } 
} 

e il test di oggi:

[TestMethod] 
    public void Verify_Some_Useful_Thing() 
    { 
     var browser = BrowserPool.Instance.Browser; 
     browser.GoTo("/someurl"); 
     // some assertions 
    } 

Questo funziona bene e i miei test funzionano molto più velocemente ora che non sto aprendo e chiudendo IE ogni test. Tuttavia, ho questo problema in quanto quando i test completano la mia istanza di IE rimarrà comunque aperta.

Non riesco a capire un modo elegante per garantire che BrowserPool.Browser dispose() o chiudi() chiamato prima che l'applicazione termini. Ho anche provato a usare un finalizzatore nella classe BrowserPool ma non sembra funzionare perché la variabile _browser era già stata recuperata quando viene chiamato il mio finalizzatore.

Come posso garantire che dispose() venga chiamato sulla mia istanza di IE dopo l'esecuzione del test?

+0

Hai provato a mettere il dispose nel distruttore di Singleton? –

+0

@ M.Babcock, ho e non ha funzionato. La variabile del browser era già stata recuperata al momento della chiamata del distruttore. – KingNestor

risposta

4

Utilizzare lo [AssemblyCleanupAttribute()] per pulire le risorse dopo aver completato i test trovati nell'assieme.

Btw, non fare mai affidamento sull'uso di distruttori in .NET.

+0

Supponendo che sia in esecuzione VS> Professional. – mxmissile

Problemi correlati