2009-03-24 4 views
8

Bei dem Versuch, einen sehr einfachen WatiN 2.0 (CTP3) -Test in Visual Studio 2008 auszuführen, habe ich festgestellt, dass der erste immer einwandfrei funktioniert. Die zweite Testmethode scheint etwas in dem IE-Objekt brechen die folgende Ausnahme produzieren:WatiN in Visual Studio 2008 - zweite Testmethode schlägt fehl

Prüfnorm testProject.WatinTest.testTwo warf Ausnahme: System.Runtime.InteropServices.InvalidComObjectException: COM-Objekt, das war getrennt vom zugrunde liegenden RCW nicht verwendet ..

Ein Beispielcode ist unten werden kann. Aufgrund der Art, wie die Initialisierungsmethode in VS2008 funktioniert, muss die Browservariable als static definiert werden, was meines Erachtens ein Schlüssel für das Problem sein könnte. Leider, wenn der Browser nicht in der üblichen Methode geöffnet wird, bedeutet dies ein separates Fenster für jeden Test, der nicht ideal ist.

Ich wäre sehr dankbar für irgendwelche Ideen, wie das zu beheben ist. Die Google-Suche und die SO-Suche haben keine nützlichen Ergebnisse erbracht, daher hoffe ich, dass eine gute Antwort auf diese Frage der Community helfen wird. Vielen Dank,


private static IE ie 

    [ClassInitialize] 
    public static void testInit(TestContext testContext) 
    { 
     ie = new IE("http://news.bbc.co.uk"); 
    } 

    [TestMethod] 
    public void testOne() 
    { 
     Assert.IsTrue(ie.ContainsText("Low graphics")); 
    } 

    [TestMethod] 
    public void testTwo() 
    { 
     Assert.IsTrue(ie.ContainsText("Low graphics")); 
    } 

Antwort

10

Ich habe dieses Problem schon einmal gehört und wollte das noch eine Weile untersuchen. Jetzt, da WatiN 2.0 Beta 1 verfügbar ist, setzte ich mich hin und erstellte eine Hilfsklasse, um dieses Problem mit dem Visual Studio Test Runner zu lösen. Nach der Helferklasse und der überarbeiteten Testklasse. Ich auch blogged über diese Lösung, um es noch mehr Exposition zu geben.

public class IEStaticInstanceHelper 
{ 
    private IE _ie; 
    private int _ieThread; 
    private string _ieHwnd; 

    public IE IE 
    { 
     get 
     { 
      var currentThreadId = GetCurrentThreadId(); 
      if (currentThreadId != _ieThread) 
      { 
       _ie = IE.AttachToIE(Find.By("hwnd", _ieHwnd)); 
       _ieThread = currentThreadId; 
      } 
      return _ie; 
     } 
     set 
     { 
      _ie = value; 
      _ieHwnd = _ie.hWnd.ToString(); 
      _ieThread = GetCurrentThreadId(); 
     } 
    } 

    private int GetCurrentThreadId() 
    { 
     return Thread.CurrentThread.GetHashCode(); 
    } 
} 

Und die Testklasse diese Helfer mit:

[TestClass] 
public class UnitTest 
{ 
    private static IEStaticInstanceHelper ieStaticInstanceHelper; 

    [ClassInitialize] 
    public static void testInit(TestContext testContext) 
    { 
     ieStaticInstanceHelper = new IEStaticInstanceHelper(); 
     ieStaticInstanceHelper.IE = new IE("http://news.bbc.co.uk"); 
    } 

    public IE IE 
    { 
     get { return ieStaticInstanceHelper.IE; } 
     set { ieStaticInstanceHelper.IE = value; } 
    } 

    [ClassCleanup] 
    public static void MyClassCleanup() 
    { 
     ieStaticInstanceHelper.IE.Close(); 
     ieStaticInstanceHelper = null; 
    } 

    [TestMethod] 
    public void testOne() 
    { 
     Assert.IsTrue(IE.ContainsText("Low graphics")); 
    } 

    [TestMethod] 
    public void testTwo() 
    { 
     Assert.IsTrue(IE.ContainsText("Low graphics")); 
    } 
} 

HTH, Jeroen

+0

Brilliant, Jeroen. Das ist eine großartige Antwort und ich hoffe wirklich, dass es vielen Leuten helfen wird, die das gleiche Problem haben. Ich hoffe auch, dass jetzt zwischen Ihrem Blog und SO Google in der Lage sein wird, sinnvolle Vorschläge zu geben, wenn Menschen nach Lösungen suchen werden. –

+0

Ich musste Nailujs Code (basierend auf Ihrem Code) für die neueste Version von WatiN verwenden. Ich bekam jedoch Ausnahmen bei ClassCleanup und konnte den Browser nicht entfernen, ohne den Prozess mit Process.Kill() zu beenden ... was eine hässliche Lösung ist :( –

0

Ich denke, es ist die Art und Weise zusammenhängt Sie einen Halt an den IE variabel zu halten. Ich habe es ohne Probleme wie in der Probe verwendet: http://watin.sourceforge.net/. Ich sehe Wattingtests als mehr funktionelle/Integrationstests als Komponententests, also ist jeder Test mehr wie eine Geschichte mit verschiedenen Interaktionen. Ich verwende das Page-Objekt-Muster, um den Code zu strukturieren - siehe http://code.google.com/p/webdriver/wiki/PageObjects.

Ps. Ich habe überlegt, die Instanz wiederzuverwenden, habe sie aber nicht wirklich ausprobiert. Das Öffnen/Schließen von Instanzen des Browsers fügt den Tests Zeit hinzu.

+0

Danke. Die Beispiele auf der WatiN-Seite funktionieren für mich, aber für die Real-Live-Szenarien würde mir etwas mehr gefallen. Wir könnten das Page Object-Muster verwenden, aber wenn Sie es hier einfügen, wird der Beispielcode unlesbar. Nochmals vielen Dank –

+0

Natürlich geht es bei WatiN nicht wirklich um Komponententests, sondern um Integration/Funktion, aber nur weil Sie Unit Test Runner ausführen, heißt das nicht, dass es Unit-Test sein muss. Wenn Sie Funktions-/Integrationstests basierend auf Komponententest-Infrastruktur schreiben, erhalten Sie Runner-, Reporting-, VS-Integration wie beim Komponententest, was BIG-Verstärkung ist, besonders wenn Sie es auf einem CI-Server ausführen möchten, wo Ihr Test jedes Mal neu ausgeführt wird Der Build der Anwendung wird bereitgestellt. – yoosiba

8

ich für diese gleiche Sache war auf der Suche, und die Antwort von jvmenen half mir aus. Es gab jedoch einige Aktualisierungen von WatiN, seit diese Antwort gegeben wurde, also musste ich die Hilfsklasse etwas umschreiben, um mit der neuesten WatiN-Version (derzeit 2.0.20) konsistent zu sein.

WatiN enthält nicht mehr die IE.AttachToIE Funktion, also musste ich das etwas ändern. Zusätzlich habe ich die Hilfsklasse mit Generics erstellt, so dass jeder Browsertyp verwendet werden kann und nicht nur IE (ich glaube, dass IE und Firefox jetzt von WatiN unterstützt werden und Chrome kommt).

sonst Also, falls jemand wird auch für diese suchen, hier ist meine Version der IEStaticInstanceHelper (jetzt StaticBrowserInstanceHelper genannt):

class StaticBrowserInstanceHelper<T> where T : Browser 
{ 
    private Browser _browser; 
    private int _browserThread; 
    private string _browserHwnd; 

    public Browser Browser 
    { 
     get 
     { 
      int currentThreadId = GetCurrentThreadId(); 
      if (currentThreadId != _browserThread) 
      { 
       _browser = Browser.AttachTo<T>(Find.By("hwnd", _browserHwnd)); 
       _browserThread = currentThreadId; 
      } 
      return _browser; 
     } 
     set 
     { 
      _browser = value; 
      _browserHwnd = _browser.hWnd.ToString(); 
      _browserThread = GetCurrentThreadId(); 
     } 
    } 

    private int GetCurrentThreadId() 
    { 
     return Thread.CurrentThread.GetHashCode(); 
    } 
} 

Hope this jemand hilft :)

Verwandte Themen