Selenium Chromedriver 在只需要一个实例时创建多个实例

Selenium Chromedriver is creating multiple instances when only one is wanted

如果我觉得我很幼稚,我深表歉意,我是 Selenium 的新手,仍在学习中。

我们正在尝试通过 IIS 在指定的机器上 运行 这些 selenium 测试。

当我在本地 运行 代码时,一切正常。当我将它发布到我们的机器上时,chromedriver 的两个实例将显示在任务管理器中,而它仅 运行 一次。有时它会关闭其中一个实例,而有时它也不会关闭。有时它甚至会关闭两个实例并正常工作。我不明白为什么它如此不一致。

这是启动代码后任务管理器的屏幕截图。

欢迎提出任何建议,下面是我运行宁的代码。

private IWebDriver _driver;

[Route("/Test_SignIn")]
public IActionResult Test_SignIn(string environment = "development")
{
    string response = "Failed";

    try
    {
        string outPutDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
        _driver = new ChromeDriver(outPutDirectory);

        if (environment == "production")
        {
            _driver.Navigate().GoToUrl(productionUrl);
        }
        else
        {
            _driver.Navigate().GoToUrl(developmentUrl);
        }

        By userNameFieldLocator = By.Id("AccountUserName");
        WebDriverWait wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(30));
        wait.Until(ExpectedConditions.ElementIsVisible(userNameFieldLocator));
        _waitForLoaderToFinish();
        IWebElement userNameField = _driver.FindElement(userNameFieldLocator);
        IWebElement passwordField = _driver.FindElement(By.Id("AccountPassword"));
        IWebElement signInButton = _driver.FindElement(By.XPath("//button[contains(text(), 'Sign In')]"));
        userNameField.SendKeys(_username);
        passwordField.SendKeys(_password);
        signInButton.Click();
        By dashboardLocator = By.Id("portalBanner_EmployeeName");

        wait.Until(ExpectedConditions.ElementIsVisible(dashboardLocator));

        IWebElement dashboard = _driver.FindElement(dashboardLocator);
        response = "Success";
    }
    catch (Exception ex)
    {
        response = ex.Message;
    }

    _driver.Close();
    _driver.Quit();

    return Json(response);
}

private string _waitForLoaderToFinish()
{
    try
    {
        new WebDriverWait(_driver, TimeSpan.FromSeconds(30)).Until(ExpectedConditions.InvisibilityOfElementLocated(By.Id("loader-wrapper")));

        return null;
    }
    catch (TimeoutException e)
    {
        return $"{e.Message}";
    }
}

ChromeDriver(以及所有其他网络驱动程序)是 .NET 中的“一次性”对象。他们实施 IDisposable interface。实现此接口的对象需要特殊处理,以便在完成后进行清理。通常您会看到这些对象在 using(...) 块中初始化,类似于以下内容:

using (IWebDriver driver = new ChromeDriver(...))
{
    // Use driver
}

参考:C# Using Statement.

我看到您正在关闭并退出浏览器,但您还需要调用 _driver.Dispose();。在代码中完成此操作的快速简便方法是在调用 Quit() 之后调用 Dispose():

_driver.Close();
_driver.Quit();
_driver.Dispose(); // <-- this kills Chrome.exe

return Json(response);

或修改方法以将 _driver 的使用包装在 using(...) 语句中:

[Route("/Test_SignIn")]
public IActionResult Test_SignIn(string environment = "development")
{
    string response = "Failed";

    try
    {
        string outPutDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

        // Your web driver is a LOCAL variable now, beware!
        using (IWebDriver driver = new ChromeDriver(outPutDirectory))
        {
            if (environment == "production")
            {
                driver.Navigate().GoToUrl(productionUrl);
            }
            else
            {
                driver.Navigate().GoToUrl(developmentUrl);
            }

            By userNameFieldLocator = By.Id("AccountUserName");
            WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
            wait.Until(ExpectedConditions.ElementIsVisible(userNameFieldLocator));
            _waitForLoaderToFinish();
            IWebElement userNameField = driver.FindElement(userNameFieldLocator);
            IWebElement passwordField = driver.FindElement(By.Id("AccountPassword"));
            IWebElement signInButton = driver.FindElement(By.XPath("//button[contains(text(), 'Sign In')]"));
            userNameField.SendKeys(_username);
            passwordField.SendKeys(_password);
            signInButton.Click();
            By dashboardLocator = By.Id("portalBanner_EmployeeName");

            wait.Until(ExpectedConditions.ElementIsVisible(dashboardLocator));

            IWebElement dashboard = driver.FindElement(dashboardLocator);
            response = "Success";
        }
    }
    catch (Exception ex)
    {
        response = ex.Message;
    }

    return Json(response);
}

请注意,您的网络驱动程序现在变成了局部变量。它不应该是 class 上的字段,以防止其他方法访问此一次性资源。