如何正确管理和访问 webdriver 实例以避免并行执行测试的问题?

How to properly manage and access webdriver instances to avoid problems with parallel execution of tests?

我在 Specflow 示例中看到了几种实例化 Web 驱动程序的方法。

  1. 在步骤定义中创建它 class 并在 class
  2. Dispose 方法中处理它

为什么可怕?原因 1 个场景不等于 1 个步骤定义 class,因为某些步骤仅在功能之间共享,并且将实例化 1 个以上的 Web 驱动程序。示例:https://www.softwaretestinghelp.com/specflow-and-selenium/

  1. 在钩子中创建它 [BeforeScenario] 并在 [AfterScenario]
  2. 中销毁 int

它不适用于并行执行(根据作者的说法)。 https://github.com/AutomateThePlanet/AutomateThePlanet-Learning-Series/tree/master/Specflow-Series/ExtendTestExecutionWorkflowUsingHooks

问题:如何使用 NUnit 管理 Specflow UI 测试解决方案中的 WebDriver 个实例?何时何地初始化它,何时何地销毁它以及如何在页面对象模型和步骤定义中访问它 classes?

您需要使用SpecFlow自带的依赖注入框架。选项 #2 在 [BeforeScenario] 中创建它并在 [AfterScenario] 中销毁它是正确的方法,但是你需要使用依赖注入框架注册 IWebDriver 对象:

[Binding]
public class WebDriverHooks
{
    private readonly IObjectContainer container;

    public WebDriverHooks(IObjectContainer container)
    {
        this.container = container;
    }

    [BeforeScenario]
    public void CreateWebDriver()
    {
        FirefoxDriver driver = new FirefoxDriver();

        // Make 'driver' available for DI
        container.RegisterInstanceAs<IWebDriver>(driver);
    }

    [AfterScenario]
    public void DestroyWebDriver()
    {
        var driver = container.Resolve<IWebDriver>();

        if (driver != null)
        {
            driver.Quit();
            driver.Dispose();
        }
    }
}

您的步骤定义需要接受 IWebDriver 对象作为构造函数参数。您甚至可以使用 DI 框架注册您的页面对象。

[Binding]
public class LoginSteps
{
    private readonly IWebDriver driver;
    private readonly LoginPage loginPage;

    public LoginSteps(IWebDriver driver)
    {
        // Assign 'driver' to private field or use it to initialize a page object
        this.driver = driver;

        // Initialize Selenium page object
        this.loginPage = new LoginPage(driver);
    }

    [When(@"I go to the login page")]
    public void WhenIGoToTheLoginPage()
    {
        // Use 'driver' in step definition
        driver.FindElement(By.LinkText("Sign In")).Click();
    }

    [When(@"I log in")]
    public void WhenILogIn()
    {
        // Use Selenium page object in step definition
        loginPage.LogIn("testUser", "testPassword");
    }
}

在您引用的 GitHub 项目中,Web 驱动程序对象被初始化为静态 属性。这就是该代码示例不能用于并行测试的原因。听起来所有执行场景都使用相同的 AppDomain,因此它们共享静态 class 状态,这意味着每个场景都试图使用相同的浏览器实例。