Selenium Grid - Do something on test failure - selenium

I am relatively new to Selenium Grid and I'm having issues with test stability. For some reason, when I'm running my tests via the grid and RemoteWebDriver, my tests intermittently get stuck on the IEDriverServer opening page that says,
"This is the initial start page for the WebDriver server."
This causes the remainder of the tests that get put against that machine to fail, which is extremely frustrating because 99 times out of 100 those same tests will pass on a rerun.
I am wanting to do something like the following but can't seem to implement it. Here is the pseudo code:
if(initialWebDriverPageTextIsOnPage > 30seconds)
{
driver.Close();
driver.Dispose();
}
I feel like this could fit in my basetest as a listener that consistently polls the page but I can't seem to figure out how to implement this.
Any advice, or suggestions as to what the root cause is would be greatly appreciated

As you want to wait for your intended url to wait for a definite period, you can induce ExplicitWait i.e WebDriverWait with proper ExpectedConditions clause as follows :
WebDriverWait wait_4_link = new WebDriverWait(driver, new TimeSpan(0,0,10));
if(wait_4_link.Until(ExpectedConditions.UrlToBe("your_intended_url")))
{
//Your Test Code
}
else
{
driver.quit();
}
As an alternative instead of the ExpectedConditions clause as UrlToBe you can also use either of the following clauses :
wait_4_link.until(ExpectedConditions.UrlContains("your_url_fraction"));
wait_4_link.until(ExpectedConditions.UrlMatches("regex_pattern_of_url"));

Related

WebElement click() not working in Selenium

I was learning automated selenium testing in https://www.yatra.com/etw-desktop/. While trying to click an image button named 'Asia'(image is attached) ,I am getting a Time out exception. Please help me in figuring out what's going wrong .
driver.manage().window().maximize();
driver.get("https://www.yatra.com/etw-desktop/");
driver.manage().timeouts().implicitlyWait(4000, TimeUnit.MILLISECONDS);
Thread.sleep(5000);
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable
(By.xpath("//*[#id=\"scrollable1\"]/div[1]/div/a[2]/div[4]"))).click();
Thread.sleep(4000);
Assert.assertEquals("https://www.yatra.com/etw-desktop/city-list",driver.getCurrentUrl());
image showing the web element to be clicked
Try this:
How to Find Web Elements in Shadow DOMs using Selenium
It is most probably because of using Thread.sleep(), which is the worst case of explicit wait. Instead use the wait method provided by selenium itself.

Alternative of Thread.sleep in selenium

In selenium testing framework I am using thread.sleep(40000). I have a requirement not to use thread.sleep()or its alternative fluent wait or any kind of wait, and keep your script engaged anyhow so that script will pick particular element after that some interval until that element actually appears on that page. Hence error wont be thrown while accessing the element. Do you have any suggestion how can I keep my script engaged for few miliseconds without using any wait ?
I use this code. You can add try catch with timeOutException.
import org.openqa.selenium.By.*;
By element = new ById("id");
long timeout;
WebElement webElement =(WebElement)(new WebDriverWait(getDriver(), timeout)).until(ExpectedConditions.visibilityOfElementLocated(element));

There is no frame but still there is an error element is not found

Below is my code, the line =>
driver.findElement(By.xpath("//*[#id=\"quote_password\"]")).sendKeys("password"); throws exception that element is not found
#Test
public void mytest()
{
System.setProperty("webdriver.chrome.driver","Drivers/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.get("http://billing.scriptinglogic.net/index.php/sessions/login");
driver.findElement(By.xpath("//*[#id='email']")).sendKeys("email");
driver.findElement(By.xpath("//*[#id='password']")).sendKeys("password");
driver.findElement(By.xpath("/html/body/div/div/form/input")).click();
driver.findElement(By.xpath("//*[text()='Quotes']")).click();
driver.findElement(By.xpath("//*[text()='Create Quote']")).click();
driver.findElement(By.xpath("//*[#id=\"quote_password\"]")).sendKeys("password");
}
Quick and dirty solution:
WebDriverWait wait = new WebDriverWait(driver, 15, 100);
driver.get("http://billing.scriptinglogic.net/index.php/sessions/login");
driver.findElement(By.id("email")).sendKeys("<EMAIL>");
driver.findElement(By.id("password")).sendKeys("<PASSWORD>");
driver.findElement(By.name("btn_login")).click();
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[text()='Quotes']"))).click();
wait.until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector(".create-quote"))).click();
wait.until(ExpectedConditions.elementToBeClickable(By.id("quote_password"))).sendKeys("password");
Updated based on the credentials supplied in the comment below. I've tweaked the selectors to use ID, name and class where applicable. There is no need to use complex XPath locators when they aren't needed.
The explicit waits are required based on the way the site is working and I've added JeffC's suggestion of using an elementToBeClickable expected condition for the input element (I don't think it's really required in this instance though since the site doesn't seem to ever disable the input field, so a visibilityOfElementLocated expected condition is just as good really).
This solution is working for me in Chrome and Firefox in standard mode and Firefox in headless mode. It's not working in headless mode in Chrome because the screen size is smaller and when the screen width goes below 1000px the header changes and the text "Quotes" is never displayed. Below 767px the header is completely removed and you get a side menu. This means that the flow of the script needs to change slightly based on resolution.
I would suggest asking your developer to add an ID to the menu items, it will make it easier to locate them and use the site in its various states. The quick and dirty solution to this problem is ensure the browser is a certain size while the test runs, you can do this by setting the size in the first line of your script:
driver.manage().window().setSize(new Dimension(1024, 768));
When you do this it passes in Firefox and Chrome in standard and headless mode.
Note: The lines with an explicit wait that result in an element being clicked are anchor elements so there is no point waiting for the element to be clickable as the condition is always going to return true.

NoSuchElementException while using Xpath with HtmlUnitDriver

I need to run Selenium in Linux machine and using HtmlUnitDriver to achieve this.
Selenium script contains most of Xpath to find the elements. While running, NoSuchElementException is getting displayed at the places where xpath is used.
org.openqa.selenium.NoSuchElementException: Unable to locate a node using //*[contains(text(),'Sample Text')]
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
The same code is working fine with other drivers like Chrome, Firefox or IE.
My code looks as below,
HtmlUnitDriverdriver = new HtmlUnitDriver();
driver.setJavascriptEnabled(true);
driver.get("http://example.com");
driver.findElement(By.id("username")).sendKeys("xxx");
driver.findElement(By.id("password")).sendKeys("yyy");
driver.findElement(By.id("loginButton")).click();
Thread.sleep(2000);
driver.findElement(By.xpath("//*[contains(text(),'Sample Text')]")).click();
I found many similar question and the solution is to provide sleep time or to wait for the element till it gets loaded. I provided everything and still facing this issue when xpath is used.
Also finding the element by ID or name is not possible in my use case as it varies everytime.
I can use only the xpath to find the text inside the span tag.
I need a solution for handling this. Thanks in advance!
Edit :
I tried the same for gmail login, Still am getting the same issue,
driver.get("http://www.gmail.com");
driver.findElement(By.id("Email")).sendKeys("xxx#gmail.com");
driver.findElement(By.id("next")).click();
Thread.sleep(2000);
driver.findElement(By.id("Passwd")).sendKeys("yyy");
driver.findElement(By.id("signIn")).click();
Thread.sleep(8000);
driver.findElement(By.xpath("//*[contains(text(),'COMPOSE')]")).click();
Consider also getting rid of text(), which might cause that kind of problem. Use this instead:
contains(., 'Sample Text')
Not sure this is the cause if your problem here, this is more of a blind shot, given the few info you gave us.
I would first of all suggest providing a more effective explicit wait, so that it will suspend until the condition is fulfilled, and also will give you the TimeoutException if you didn't provide long enough timeout.
//This will store your locator for later use
By elementLocator = By.xpath("//*[contains(text(),'Sample Text')]");
//This creates a reusable wait object
WebDriverWait wait = new WebDriverWait(browser.driver, 15);
//Waiting is stopped right after the condition is satisfied or timeout (set in the previous line, in secs) was reached
wait.until(ExpectedConditions.elementToBeClickable(elementLocator));
If you are getting the same error you can try this
try {
wait.until(ExpectedConditions.elementToBeClickable(elementLocator));
} catch (org.openqa.selenium.TimeoutException e) {
System.out.println(driver.getPageSource());
}
To see whether the element is present on the page you are looking for it.

How to make xpath work with Selenium when filepicker.io is loaded

After implementing filepicker.io, some of our Selenium regression tests have started failing. The failures (intermittent, but more often than not in some circumstances) are that clicks are ignored on WebElements found via XPath queries. e.g.
driver.findElement(By.xpath("//a[text()='Demo data']")).click();
Adding a Sleep(2000) between findElement() and click() generally resolves the problem. (I say generally because Sleep(1000) was mostly enough, until it wasn't, so I made it Sleep(2000)...)
Checking element.isDisplayed() has not helped. The problem disappears if we stop including the filepicker.io JavaScript file.
Is it something to do with filepicker.io introducing an IFRAME? We have also noticed that JQuery's document.ready() seems to be now invoked twice.
As usual with this kind of problems, you are trying to find an element that is not yet available on the page due to AJAX request still downloading/processing it. You need to wait for the element to appear on the page.
There are three ways to do this:
Using sleep(). This is the discouraged way. You should not use hardcoded sleeps, because you'll either wait too long (making the tests unnecessarily slow) or too short (failing the test).
Use Implicit wait. That will always wait for an element if it's not found.
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
Use explicit wait. That enables you to wait explicitly for one element to (dis)appear / become available / whatever.
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.linkText("Demo data")));
We now run this code first after opening any page that includes filepicker.js:
while (FindElementsMaybeNone(By.cssSelector("#filepicker_comm_iframe")).size() == 0)
Sleep(50);
while (driver.switchTo().frame("filepicker_comm_iframe") == null)
Sleep(50);
driver.switchTo().defaultContent();
We guess that filepicker's dynamic IFRAME insertion is discombobulating Firefox or Selenium. I'm not marking this as the answer because I don't really know why it works.