首页 > 解决方案 > 当只需要一个时,Selenium Chromedriver 正在创建多个实例

问题描述

如果我遇到幼稚的问题,我深表歉意,我是 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}";
    }
}

标签: c#selenium.net-coreselenium-chromedriver

解决方案


ChromeDriver(和所有其他 Web 驱动程序)是 .NET 中的“一次性”对象。他们实现了IDisposable 接口。实现此接口的对象需要特殊处理才能在完成后进行清理。通常,您会看到这些对象在一个using(...)块中初始化,如下所示:

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

参考:C# Using 语句

我看到您正在关闭并退出浏览器,但您也需要调用_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);
}

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


推荐阅读