I apologize if I come across naïve, I am new to Selenium and still learning.
We are attempting to run these selenium tests on a designated machine via IIS.
When I run the code locally, everything works perfectly. When I publish it to our machine, two instances of chromedriver will show up in the taskmanager when it is only being run once. Sometimes it will close one of the instances, while other times it doesn't close either. Sometimes it will even close both instances and work just fine. I can not figure out why it's being so inconsistent.
Here is a screen shot of the task manager after starting the code.
Any suggestions on this is welcome, below is the code I am running.
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}";
}
}
CodePudding user response:
ChromeDriver (and all other web drivers) are "disposable" objects in .NET. They implement the IDisposable interface. Objects that implement this interface require special handling in order to clean up after they are finished. Typically you see these objects initialized in a using(...)
block, similar to below:
using (IWebDriver driver = new ChromeDriver(...))
{
// Use driver
}
Reference: C# Using Statement.
I see that you are closing and quitting the browser, but you need to call _driver.Dispose();
as well. The quick and easy way to accomplish this in your code is to call Dispose() after calling Quit():
_driver.Close();
_driver.Quit();
_driver.Dispose(); // <-- this kills Chrome.exe
return Json(response);
Or modify the method to wrap the use of _driver
in a using(...)
statement:
[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);
}
Please note that your web driver becomes a local variable now. It should not be a field on the class in order to prevent other methods from accessing this disposable resource.