【问题标题】:Run WebDriver NUnit tests on multiple drivers在多个驱动程序上运行 WebDriver NUnit 测试
【发布时间】:2012-09-11 14:52:35
【问题描述】:

我们最近开始使用 WebDriver(支持 Selenium 1)执行浏览器测试,使用 NUnit 框架。由于我们想在各种浏览器中运行测试,我们为每个浏览器定义驱动程序,并在夹具设置期间将它们放在一个列表中:

[TestFixtureSetUp]
public void SetupTest()
{
    // Load drivers
    Drivers = new List<IWebDriver>
            {
                new ChromeDriver(),
                ...
            };

在每个测试中,我们都会像这样遍历列表:

[Test]
public void SomeTest()
{
    foreach (var driver in Drivers)
    {
        driver.Navigate().GoToUrl("...");
...

在所有的测试方法中都这样做感觉不对。测试方法不应该关心他们应该使用什么驱动程序。理想情况下,我们会有这样的东西:

public void SomeTest(IWebDriver driver)
{
    driver.Navigate().GoToUrl("...");
...

我们可以解决这个问题的一种方法是使用 TestCases:

[TestCase(new ChromeDriver())]
[TestCase(new FireFoxDriver())]
...

但是这是很多重复,并且将驱动程序的正确初始化问题转移到每个测试的属性中。不是真正的收获。

有什么方法可以告诉 NUnit 框架执行整套测试并在每次运行时为各个测试注入不同的参数?或者有没有其他好的解决方案?

【问题讨论】:

    标签: c# nunit webdriver


    【解决方案1】:

    您应该可以使用TestCaseSourceAttribute。首先创建一个提供 Web 驱动程序集合的常用类:

    public static class WebDriverFactory
    {
        public static IWebDriver[] Drivers =
        {
            new ChromeDriver(),
            new FirefoxDriver(),
            ...
        };
    }
    

    接下来,像这样实现依赖于 Web 驱动程序的单元测试:

    [Test, TestCaseSource(typeof(WebDriverFactory), "Drivers")]
    public void SomeTest(IWebDriver driver)
    {
        driver.Navigate().GoToUrl("...");
        ...
    }
    

    可选地,为了在实现每个单元测试时减少打字,还定义一个新的 Attribute 类,该类继承自 TestCaseSourceAttribute 并且仅实现默认构造函数:

    public class WebDriverSourceAttribute : TestCaseSourceAttribute
    {
        public WebDriverSourceAttribute() : base(typeof(WebDriverFactory), "Drivers")
        {            
        }
    }
    

    使用继承的WedDriverSource 属性,单元测试现在可以简化为:

    [Test, WebDriverSource]
    public void SomeTest(IWebDriver driver)
    {
        driver.Navigate().GoToUrl("...");
        ...
    }
    

    【讨论】:

    • 谢谢,这是朝着正确方向迈出的一步。不过,必须为每个测试声明这个属性仍然不是很优雅。
    • 我明白你的意思,我同意。请查看更新后的答案以了解更优雅的方法。
    • 两年后看这个,我意识到我更喜欢这个解决方案。它从测试/测试夹具中删除了浏览器/驱动程序的显式列表,并且不需要测试的基类。是否可以将[Test][WebDriverSource] 组合成一个属性[WebDriverTest]?我得试试看。
    • 你能澄清WebDriverSourceAttribute的用途或可以用来做什么吗?
    【解决方案2】:

    没有“最好”的方法可以做到这一点,但是我完成的方法如下:

    我创建了一个枚举:

    /// <summary>
    /// Enum that holds references to different browsers used in testing.
    /// </summary>
    public enum BrowserTypeEnum
    {
        /// <summary>
        /// Google Chrome.
        /// </summary>
        Chrome, 
    
        /// <summary>
        /// Mozilla Firefox.
        /// </summary>
        Firefox, 
    
        /// <summary>
        /// Internet Explorer.
        /// </summary>
        InternetExplorer
    }
    

    在 TestFixture 中这样调用它:

    /// <summary>
    /// Tests related to browsing Google
    /// </summary>
    [TestFixture(BrowserTypeEnum.Chrome)]
    [TestFixture(BrowserTypeEnum.Firefox)]
    public class GoogleTests : AbstractTestFixture
    {
    }
    

    在 AbstractTestFixture 中:

        /// <summary>
        /// Create's the browser used for this test fixture. 
        /// <para>
        /// Must always be called as part of the test fixture set up.
        /// </para>
        /// <para>
        /// It is the actual test fixture's responsibility to launch the browser. (Usually in the test fixture setup)
        /// </para>
        /// </summary>
        protected override void CreateBrowser()
        {
            switch (BrowserType)
            {
                case BrowserTypeEnum.Chrome:
                    Browser = new ChromeDriver();
                    break;
                case BrowserTypeEnum.Firefox:
                    Browser = new FirefoxDriver();
                    break;
                case BrowserTypeEnum.InternetExplorer:
                    Browser = new IEDriver();
                    break;
                default:
                    break;
            }
        }
    

    可能不是最好的解决方案,但我发现它非常易读。另一种方法是使用 Selenium Grid 之类的东西,或者将驱动程序的类型传递给 NUnit 并直接创建它。您已经尝试过(通过直接类型的驱动程序),但它似乎不是您所追求的。唯一的区别可能是您将驱动程序的类型传入测试夹具,而不是实际测试。

    另一种选择是,如果您使用 CI 服务器解决方案,请创建一个配置设置以指示用于测试的浏览器。让 CI 驱动程序重复测试 3 次,每次都编辑该配置设置。

    我同意,知道他们正在使用什么样的驱动程序并不是实际的测试责任,这就是为什么我将这个责任向上推到测试夹具中。我这样做的方式可能不是最“优雅”的方式,但至少对我来说是最易读的。看到我的代码的人可以很容易地看到这个测试夹具正在重复,以及哪些浏览器正在重复这些步骤。

    对我来说,驱动程序的创建必须始终在实际的 TestFixture(而不是基本测试夹具)中。原因是因为在打开浏览器之前我想做一些逻辑 - 如果这个逻辑失败(在 Setup 或 TestFixtureSetup 方法中),那么 NUnit 将不会运行任何拆卸方法。因此,浏览器窗口将保持打开状态。

    因此,为了解决这个问题,我在 TestFixtureSetup 中做的最后一件事是在运行测试之前称为“CreateBrowser”。

    【讨论】:

      【解决方案3】:

      您还可以为 NUnit 编写自己的 TestCaseProvider 插件,以便在所有浏览器上执行此迭代。

      然后像这样新建一个属性

      [Test, TestOnAllBrowsers]
      public void SomeTest(IWebDriver driver)
      {
          driver.Navigate().GoToUrl("...");
      }
      

      标记应在所有浏览器上运行的所有测试,并在 TestCaseProvider 插件中填充 driver 变量。但是,如果您已经使用了 TestCase 属性,这可能会变得复杂。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多