I have a selenium test in Java and I am doing some assertions like that:
assertFalse(isElementPresent(By.xpath("//td[2]/div")));
private boolean isElementPresent(By by) {
try { driver.findElement(by); return true; }
catch (NoSuchElementException e) {
return false; }
It´s the standard method Selenium is generating when export from IDE to Java Webdriver.
(Yes I want to assert that this element is not present)
I always get errors when I am testing at this above code line
Error: stale element reference: element is not attached to the DOM
But when I put a thread.sleep in front of that step it works.
The fact I don´t get is that it is enough to wait 1 milli sec.
Is it typical to wait before an assertion?
Is there another way to solve this? (Implicit wait is not helping here)
Greetings from Germany!
As you are facing staleelementreferenceexception in assertFalse() function, to negate the FalsePossitive usecase you can induce WebDriverWait with ExpectedConditions clause set to stalenessOf within assertTrue() function as follows :
Assert.assertTrue(new WebDriverWait(driver, 20).until(ExpectedConditions.stalenessOf(driver.findElement(By.xpath("//td[2]/div")))));
Explaination
The ExpectedConditions clause stalenessOf will check for the staleness of the element identified as (By.xpath("//td[2]/div")). When the intended element becomes stale, you can check for assertTrue(boolean condition). assertTrue() would assert that a condition is true. If it isn't, an AssertionError would be raised.
assertFalse(condition)
If you still want to implement the FalsePossitive case of assertFalse(condition) raising Error you still can :
Assert.assertFalse(new WebDriverWait(driver, 20).until(ExpectedConditions.stalenessOf(driver.findElement(By.xpath("//td[2]/div")))));
I think, timeouts are not set to WebDriver. try this
assertFalse(isElementPresent(By.xpath("//td[2]/div")));
private boolean isElementPresent(By by) {
driver.timeouts().implicitlyWait(5, TimeUnit.SECONDS);
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
try { driver.findElement(by); return true; }
catch (NoSuchElementException e) {
return false; }
Related
I am new to Selenium.
My issue is that I'm trying to click an element but Selenium is throwing a timeout exception, even if I increase the timeout value.
Do I need to use xpath instead of id?
The HTML Code is:
My code looks like this
void searchquotation() throws TimeoutException {
try {
WebDriverWait wait = new WebDriverWait(driver, 15);
WebElement element = wait.until(ExpectedConditions.presenceOfElementLocated(By.name("SearchButton")));
element.click();
}
catch(TimeoutException e) {
System.out.println("Timeout occured");
}
Am I doing anything wrong?
The input type here is submit (by looking at your HTML code) so I would strongly advise to try the submit() function of Selenium.
Instead of By.name, you should use By.id instead. Therefore, use either of these:
By.Id("SearchButton")
By.CssSelector("input#SearchButton")
By.Xpath("//input[#id='SearchButton']")
Note: syntax could be wrong, please adjust depending on your programming language
try below code, even timeout exception occurs, it will try 4 time to click on it. assuming locator is correct By.name("SearchButton")
public void searchquotation()
int count=0;
while(count<4)
{
try {
WebElement x = driver.findElement(By.name("SearchButton")));
WebDriverWait element=new WebDriverWait(driver,15);
element.until (ExpectedConditions.presenceOfElementLocated(By.name("SearchButton")));
x.click();
count=count+4;
}
catch(TimeoutException e) {
count=count+1;
System.out.println("Timeout occured");
continue;
}
}
I'm currently checking to see if a WebElement is stale by doing the following:
public static boolean isStale(WebElement element) {
try {
element.click();
return false;
} catch (StaleElementReferenceException sere) {
return true;
}
}
This is the same as the solution offered to this question:
Check for a stale element using selenium 2?
However, this seems rather messy to me. Is there a cleaner way that I can check if an element is stale, without having to throw and catch an exception?
(Also, as a side, if I have to stick with throwing and catching an exception, is there something better to do than clicking/sending keys/hovering to throw said exception? I might have a WebElement that I don't want to do any of these actions on, as it may inadvertently affect something else.)
Webdriver itself uses the try/catch-construction to check for staleness as well.
from org.openqa.selenium.support.ui.ExpectedConditions.java:
public static ExpectedCondition<Boolean> stalenessOf(final WebElement element) {
return new ExpectedCondition<Boolean>() {
#Override
public Boolean apply(WebDriver ignored) {
try {
// Calling any method forces a staleness check
element.isEnabled();
return false;
} catch (StaleElementReferenceException expected) {
return true;
}
}
#Override
public String toString() {
return String.format("element (%s) to become stale", element);
}
};
}
The isEnabled() check is better than using a click action - clicking an element might cause unwanted side effects, and you just want to check the element's state.
I know this already has an accepted answer and I don't know the bigger context of how you use the staleness check but maybe this will help you or others. You can have ExpectedConditions.stalenessOf(WebElement) do the work for you. For example,
WebElement pageElement = driver.findElement(By.id("someId"));
WebDriverWait wait = new WebDriverWait(webDriver, 10);
// do something that changes state of pageElement
wait.until(ExpectedConditions.stalenessOf(pageElement));
In this case, you don't have to do pageElement.click(), etc. to trigger the check.
From the docs, .stalenessOf() waits until an element is no longer attached to the DOM.
References: ExpectedConditions
Classic statement for C# to check staleness of web element
protected bool IsStale
{
get { return ExpectedConditions.StalenessOf(webElement)(WebDriver); }
}
I don't fully understand what you want to do. What do you mean by 'messy' solution?
Maybe you can use an explicite wait an as expected condition stalenessOf in combination with not.
But every solution with that don't seems stable to me.
What I do is, that I have an clicking routine in a helperclass, the idea is like:
public void ClickHelper(WebDriver driver, By by){
int counter = 1;
int max = 5;
while (counter <= max) {
try {
WebElement clickableWebElement = driver.findElement(by);
clickableWebElement.click();
return;
} catch (StaleElementReferenceException e) {
System.out.print("\nTry " + counter + " with StaleElementReferenceException:\n" + e.getMessage() + "\n");
}
versuche++;
}
throw new RuntimeException("We tried " + max + " times, but there is still an Exception. Check Log!");
}
Be careful, I just entered this by simplyfying my own methode (there are some more checks and personally I use xpath and not by etc). There might be some typo-mistakes, but i guess you will understand the basic idea. Since I use this Helpermethode, I don't have to care about Staleness of webelements. You can alter the max-value, but personally I think, if the website is such unstable, that the Element is stale so much, I would talk to the developer, because this would not be a good website.
This should work without dependency of display/ enabled:
def is_element_on_page(element):
try:
element.get_attribute('')
return True
except StaleElementReferenceException:
return False
I am using below code to check for element on my web page
private boolean isElementPresent(By by) {
try {
driver.findElement(by);
return true;
} catch (NoSuchElementException e) {
return false;
}
catch (Exception e)
{
return false;
}
}
I need to check in my program if a particular region appears in result as below
isElementPresent(By.xpath(".//*[#id='header']")));
If this is present this function completes quickly but if above is not present then it run for very long.
Could some one please help me in resolving this issue so that this check can be performed quickly?
Here you are missing somethings that is why it is waiting If there is not element. findElement will wait for an element implicitly specified time. so need to set that time to zero in that method.
isElementPresent(WebDriver driver, By by) {
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
try {
driver.findElement(by);
return true;
} catch (NoSuchElementException e) {
return false;
} finally {
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
}
}
There are 4 important things going on here. In order:
Setting implicity_wait to 0 so that WebDriver does not implicitly wait.
Returning True when the element is found.
Catching the NoSuchElementException and returning False when we discover that the element is not present instead of stopping the test with an exception.
Setting implicitly_wait back to 30 after the action is complete so that WebDriver will implicitly wait in future.
Apparently, it's long to send the exception because your DOM is big and the xpath isn't the fastest way to get an element. But if you want to use xpath, try to put the best path and avoid that kind of function where is substring checking.
Your actual xpath : .//*[#id='header'] takes so long because you check all tags of your DOM. So if put the tag that what you're looking for, example : you want to catch an input. your xpath should start like that //input[#id='1234'] and it will be shorter than looking all tags.
I'm using Selenium Webdriver and have run into the following issue with my app under test.
The app has multiple pages each with an appropriate ".page-title" element which contains the name of the page (e.g. "Other Documents"). As the tests navigate around the app they assert that the browser is on the expected page using these elements before doing other stuff.
The issue is that if you click a button in the app which performs an action, then check that you're on the right page (e.g. check page-title element displays correct text), Webdriver doesn't wait for the action to be performed (e.g. new page load), it returns straight away and the test fails.
If you add a short thread sleep (500ms) between performing the action and checking you're on the right page, then you get StaleElementReferenceException (some of the time) and if you add a large thread sleep the test passes (but not quite all the time).
My aim is to reduce the flakiness of the tests, does anyone have a suggestion as to how I can do this without Thread.sleep?
instead of inserting thread.sleep method explicity
do try the WebDriver in built Implicitwait method..(C# code snippet)
Driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(Max_Time_Limit));
This makes WebDriver to wait till the element is visible/available. In case if it finds elements before the Max_Time_Limit, it snaps out of sleep mode and resumes the execution.
So no hassle of waiting till the Hard bound Max_Time_Limit.This way it helps speeding up your execution Time as well.
I hope this helps...All the best :-)
Try using this wait: using this you can wait for max time 15 secs/wait for the expected condition to be true i.e. wait for some element to be present.
You can give the xpath of some element on the next page, when that element is visible then the next step will be executed.
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("\xpath of some element on the next page")));
//Assert page title
driver.getTitle();
use fluentWait mechanism . Considered to be a robust approach. As documentation on fluent wait gives:
An implementation of the Wait interface that may have its timeout and polling interval configured on the fly.
Each FluentWait instance defines the maximum amount of time to wait for a condition, as well as the frequency with which to check the condition. Furthermore, the user may configure the wait to ignore specific types of exceptions whilst waiting, such as NoSuchElementExceptions when searching for an element on the page.
details you can get here
here is the code of method I use:
public WebElement fluentWait(final By locator){
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, TimeUnit.SECONDS)
.pollingEvery(5, TimeUnit.SECONDS)
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(
new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
}
);
return foo; } ;
String xPathElement="...blablabla...";
fluentWait(By.xpath(xPathElement)).click();
//fluentWait(By.xpath(xPathElement)).getText();
Hope it works for you.
You can use Selenium's ExpectedCondition.
The code below (written in JAVA) waits for a maximum of inTimeout seconds for the element you want to appear. If the element appears sooner, it ends the wait.
public static void wait(WebDriver b,long inTimeout) {
final SlnDriver browser=b;
final long NO_LOADING_TIMEOUT = inTimeout;
class HasCondition implements ExpectedCondition<Boolean> {
#Override
public Boolean apply(WebDriver d) {
Boolean expected=false;
WebElement e = browser.findElement(By.xpath("blabla"));
if (e.getText().contains("TextYouWant")) {
expected= true;
break;
}
}
return expected;
}
}
}
for (;;) {
try {
new WebDriverWait(browser, NO_LOADING_TIMEOUT).until(new HasCondition());
} catch (TimeoutException e) {
return;
}
}
}
I am new to Selenium WebDriver and am trying to understand the correct way to 'wait' for elements to be present.
I am testing a page with a bunch of questions that have radio button answers. As you select answers, Javascript may enable/disable some of the questions on the page.
The problem seems to be that Selenium is 'clicking too fast' and not waiting for the Javascript to finish. I have tried solving this problem in two ways - explicit waits solved the problem. Specifically, this works, and solves my issue:
private static WebElement findElement(final WebDriver driver, final By locator, final int timeoutSeconds) {
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(timeoutSeconds, TimeUnit.SECONDS)
.pollingEvery(500, TimeUnit.MILLISECONDS)
.ignoring(NoSuchElementException.class);
return wait.until(new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver webDriver) {
return driver.findElement(locator);
}
});
}
However, I would prefer to use an implicit wait instead of this. I have my web driver configured like this:
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
This does not solve the problem and I get a NoSuchElementException. Additionally, I do not notice a 10 second pause - it just errors out immediately. I have verified this line in the code is being hit with a debugger. What am I doing wrong? Why does implicitlyWait not wait for the element to appear, but FluentWait does?
Note: As I mentioned I already have a work around, I really just want to know why Implicit wait isn't solving my issue. Thanks.
Remember that there is a difference between several scenarios:
An element not being present at all in the DOM.
An element being present in the DOM but not visible.
An element being present in the DOM but not enabled. (i.e. clickable)
My guess is that if some of the page is being displayed with javascript, the elements are already present in the browser DOM, but are not visible. The implicit wait only waits for an element to appear in the DOM, so it returns immediately, but when you try to interact with the element you get a NoSuchElementException. You could test this hypothesis by writing a helper method that explicits waits for an element to be be visible or clickable.
Some examples (in Java):
public WebElement getWhenVisible(By locator, int timeout) {
WebElement element = null;
WebDriverWait wait = new WebDriverWait(driver, timeout);
element = wait.until(ExpectedConditions.visibilityOfElementLocated(locator));
return element;
}
public void clickWhenReady(By locator, int timeout) {
WebDriverWait wait = new WebDriverWait(driver, timeout);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(locator));
element.click();
}
basic idea is in the following:
Explicit wait
WebDriverWait.until(condition-that-finds-the-element);
Implicit wait
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
In other words, explicit is associated with some condition to be held, whereas implicit with some time to wait for something.
see this link
To make work fluentWait properly try this:
public WebElement fluentWait(final By locator){
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(Duration.ofSeconds(30))
.pollingEvery(Duration.ofMillis(100))
.ignoring(NoSuchElementException.class);
WebElement foo = wait.until(
new Function<WebDriver, WebElement>() {
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
}
);
return foo;
};
Hope this helps)
Word of warning for a common mistake:
Once you set implicit waiting, you cannot use explicit- or fluent wait until you reset the implicit waiting again. This means that ExpectedConditions, which contain driver.findElement calls will not work as expected with implicit wait! You'll often encounter cases where you want to check for an element or its non-existence instantly - but you can't do that either.
After ~2 years of experience and problems with this I strongly recommend against using implicit wait.
A kotlin version of the https://stackoverflow.com/users/503060/hedley answer:
clickWhenReady("#suggest",10,driver)
via
fun clickWhenReady(selector: String,timeout: Long, webdriver: WebDriver?) {
val wait = WebDriverWait(webdriver, timeout);
val element = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector(selector)));
element.click();
}
I wrote a small method in C# using the WebDriverWait class. Works great for me.
public static void WaitForAjaxElement(IWebDriver driver, By byElement, double timeoutSeconds)
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutSeconds));
wait.Until(x => x.FindElement(byElement));
}
Using:
WaitForAjaxElement(driver, By.ClassName("ui-menu-item"), 10);
Hope it helps.
From Seleniumhq.com:
An implicit wait is to tell WebDriver to poll the DOM for a certain amount of time when trying to find an element or elements if they are not immediately available. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object instance.
If you post your test code what you actually want to do I can provide more information.
I have another solution to solve this issue (only for IE, i never try other browser):
1) after create Selenium driver instance, you can get its ie COM instance
Add-Type -Path .\SePSX.NET35\WebDriver.dll
$ieDriver = New-Object "OpenQA.Selenium.IE.InternetExplorerDriver"
$ieShell = $null
$shell_apps = (New-Object -ComObject Shell.Application).Windows()
foreach($app in $shell_apps)
{
if ($app.LocationURL -eq $ieDriver.URL)
{
$ieShell = $app
break
}
}
if ($ieShell -eq $null)
{
throw "Can't get WebDriver IE Instance"
}
2) after each call GotoURL or click action, check $ieShell.Busy status, it will wait for until page is loaded.
$ieDriver.Navigate().GotoUrl("www.google.com")
while ($ieShell.Busy -eq $true) {sleep 1}
then call Selenium driver to get element id and do the further action
$ieDriver.FindElementById ...
use this way, you don't need to set page load and findElement timeout for Selenium
import org.openqa.selenium.NoSuchElementException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver);
wait.pollingEvery(250, TimeUnit.MILLISECONDS);
wait.withTimeout(20, TimeUnit.SECONDS);
wait.ignoring(NoSuchElementException.class);
Predicate<WebDriver> predicate = new Predicate <WebDriver>()
{
public boolean apply(WebDriver arg0) {
WebElement element = arg0.findElement(By.id("colorVar"));
String color = element.getAttribute("color");
System.out.println("The color if the button is " + color);
if(color.equals("blue"))
{
return true;
}
return false;
}
};
wait.until(predicate);
Below is the code equivalet code for fluient wait in c#.Net using DefaultWait.
IWait<IWebDriver> wait = new DefaultWait<IWebDriver>(driver);
wait.Timeout = TimeSpan.FromSeconds(10);
wait.PollingInterval = TimeSpan.FromMilliseconds(100);
IWebElement elementt = wait.Until<IWebElement>(ExpectedConditions.ElementIsVisible(By.Id("selectedfirstlast1")));
SelectElement se = new SelectElement(driver.FindElement(By.Id("selectedfirstlast1")));
element = se.SelectedOption;
if (element.Text.Contains("Mumbai") && element.Selected)
driver.FindElement(By.XPath("//table/tbody/tr[2]/td[7]/a")).Click();