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
}
我看到您正在关闭并退出浏览器,但您还需要调用 _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 上的字段,以防止其他方法访问此一次性资源。
如果我觉得我很幼稚,我深表歉意,我是 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
}
我看到您正在关闭并退出浏览器,但您还需要调用 _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 上的字段,以防止其他方法访问此一次性资源。