【问题标题】:WatiN in Visual Studio 2008 - second test method failsVisual Studio 2008 中的 WatiN - 第二种测试方法失败
【发布时间】:2009-03-24 21:35:50
【问题描述】:

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

测试方法 testProject.WatinTest.testTwo 扔了 例外: System.Runtime.InteropServices.InvalidComObjectException: 已分离的 COM 对象 从其基础 RCW 不能 用过..

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

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


    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"));
    }

【问题讨论】:

    标签: visual-studio testing automation watin


    【解决方案1】:

    我之前听说过这个问题,并打算调查一段时间。现在 WatiN 2.0 beta 1 已经可用,我坐下来创建了一个帮助类来使用 Visual Studios 测试运行器解决这个问题。跟随助手类和改进的测试类。我还 blogged 介绍了这个解决方案,以使其获得更多曝光。

    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"));
        }
    }
    

    HTH, 杰伦

    【讨论】:

    • 太棒了,杰罗恩。这是一个很好的答案,我真的希望它能帮助很多有同样问题的人。我也希望现在在您的博客和 SO Google 之间能够在人们搜索解决方案时提供有意义的建议
    • 我不得不使用 Nailuj 的代码(基于您的代码)来获取最新版本的 WatiN。但是,我在 ClassCleanup 上遇到异常并且无法让浏览器在不使用 Process.Kill() 杀死进程的情况下进行处理......这是一个丑陋的解决方案:(
    【解决方案2】:

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

    WatiN 不再包含 IE.AttachToIE 函数,所以我不得不稍微修改一下。另外我还使用泛型制作了辅助类,这样任何浏览器类型都可以使用,而不仅仅是 IE(我相信现在 WatiN 支持 IE 和 Firefox,Chrome 即将到来)。

    所以如果其他人也在寻找这个,这是我的IEStaticInstanceHelper 版本(现在称为StaticBrowserInstanceHelper):

    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();
        }
    }
    

    希望这对某人有帮助:)

    【讨论】:

      【解决方案3】:

      我认为这与您保留 IE 变量的方式有关。我一直在毫无问题地使用它,如示例:http://watin.sourceforge.net/。我将 watin 测试视为比单元测试更多的功能/集成测试,因此每个测试更像是一个具有不同交互的故事。我使用页面对象模式来帮助构建代码 - 请参阅 http://code.google.com/p/webdriver/wiki/PageObjects

      附言。我考虑过重用该实例,但还没有真正尝试过。打开/关闭浏览器实例确实会增加测试时间。

      【讨论】:

      • 谢谢。 WatiN 页面上的示例对我来说效果很好,但对于真实的场景,我想要更多的东西。我们可以使用页面对象模式,但将其放在这里会使示例代码不可读。再次感谢
      • 当然,WatiN 并不是真正的单元测试,而是集成/功能,但仅仅因为您运行单元测试运行器,并不意味着它必须是单元测试。如果您基于单元测试基础设施编写功能/集成测试,您将获得像单元测试一样的运行器、报告、VS 集成,这是很大的收获,特别是如果您想在 CI 服务器上运行它,您的测试每次都会在新服务器上执行应用程序的构建已部署。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-12
      • 1970-01-01
      相关资源
      最近更新 更多