Visual studio Visual Studio 2008中的WatiN-第二种测试方法失败

Visual studio Visual Studio 2008中的WatiN-第二种测试方法失败,visual-studio,testing,automation,watin,Visual Studio,Testing,Automation,Watin,在VisualStudio2008中尝试运行一个非常简单的Watin2.0(CTP3)测试时,我发现第一个测试总是执行得很好。第二种测试方法似乎破坏了IE对象中的某些内容,产生了以下异常: 试验方法 testProject.watinest.testTwo抛出 例外情况: System.Runtime.InteropServices.InvalidComObject异常: 已分离的COM对象 不能从其基础RCW 过去的 下面是一个示例代码。由于VS2008中初始化方法的工作方式,浏览器变量必须定

在VisualStudio2008中尝试运行一个非常简单的Watin2.0(CTP3)测试时,我发现第一个测试总是执行得很好。第二种测试方法似乎破坏了IE对象中的某些内容,产生了以下异常:

试验方法 testProject.watinest.testTwo抛出 例外情况: System.Runtime.InteropServices.InvalidComObject异常: 已分离的COM对象 不能从其基础RCW 过去的

下面是一个示例代码。由于VS2008中初始化方法的工作方式,浏览器变量必须定义为
static
,我认为这可能是问题的关键。不幸的是,除非用普通方法打开浏览器,否则这意味着每个测试都有一个单独的窗口,这并不理想

如果有任何关于如何解决这个问题的想法,我将不胜感激。 谷歌搜索,所以搜索没有产生任何有用的结果,所以我希望这个问题的好答案将有助于社区。非常感谢,



我认为这与保持IE变量的方式有关。我一直在使用它,没有遇到任何问题,如示例:。我认为watin测试比单元测试更像功能/集成测试,因此每个测试更像是一个具有不同交互的故事。我使用页面对象模式来帮助构建代码-请参阅


另外,我已经考虑过重用这个实例,但还没有真正尝试过。打开/关闭浏览器实例确实会为测试增加时间。

我以前听说过这个问题,打算对此进行一段时间的研究。现在WatiN 2.0 beta 1可用了,我坐下来创建了一个帮助器类,用Visual Studio test runner解决这个问题。遵循helper类和改进的测试类。我还对这个解决方案进行了讨论,以使其更加暴露

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();
    }
}
以及使用此帮助器的测试类:

[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"));
    }
}
嗯,,
杰罗恩

我也在寻找同样的东西,jvmenen的回答帮助了我。然而,自从给出这个答案以来,WatiN已经有了一些更新,所以我不得不稍微重写helper类以与最新的WatiN版本(目前为2.0.20)保持一致

WatiN不再包含
IE.AttachToIE
函数,所以我不得不稍微修改一下。此外,我还使用泛型创建了helper类,因此可以使用任何浏览器类型,而不仅仅是IE(我相信现在WatiN支持IE和Firefox,Chrome也将支持)

因此,如果其他任何人也在寻找这个,下面是我的版本的
IEStaticInstanceHelper
(现在称为
StaticBrowserInstanceHelper
):

类StaticBrowserInstanceHelper,其中T:Browser
{
专用浏览器(u Browser),;
私有int_浏览器线程;
私有字符串_browserHwnd;
公共浏览器
{
得到
{
int currentThreadId=GetCurrentThreadId();
如果(currentThreadId!=\u browserThread)
{
_browser=browser.AttachTo(Find.By(“hwnd”),_browserHwnd);
_browserThread=currentThreadId;
}
返回浏览器;
}
设置
{
_浏览器=值;
_browserHwnd=_browser.hWnd.ToString();
_browserThread=GetCurrentThreadId();
}
}
私有int GetCurrentThreadId()
{
返回Thread.CurrentThread.GetHashCode();
}
}

希望这对某人有所帮助:)

谢谢。WatiN页面上的例子对我来说很好,但是对于真实的场景,我想要更多。我们可以使用页面对象模式,但将其放在这里会使示例代码不可读。再次感谢您,当然WatiN并不是关于单元测试,而是关于集成/功能,但仅仅因为您运行了单元测试运行程序,并不意味着它必须是单元测试。如果您基于单元测试基础架构编写功能/集成测试,您将获得runner、reporting和与单元测试类似的VS集成,这是一个很大的好处,特别是如果您希望在CI服务器上运行它,每次部署新的应用程序构建时,您的测试都会在该服务器上执行。Brilliant,Jeroen。这是一个很好的答案,我真的希望它能帮助很多有同样问题的人。另外,我希望现在在你的博客和谷歌之间,当人们搜索解决方案时,谷歌能够给出有意义的建议。我不得不使用Nailuj的代码(基于你的代码)来获取最新版本的WatiN。但是,我在ClassCleanup上遇到异常,无法让浏览器在不使用Process.Kill()终止进程的情况下进行处理。。。这是一个丑陋的解决方案:(
[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"));
    }
}
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();
    }
}