I'm working on a Java Selenium-WebDriver. I added
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
and
WebElement textbox = driver.findElement(By.id("textbox"));
because my Applications takes few seconds to load the User Interface. So I set 2 seconds implicitwait. but I got unable to locate element textbox
Then I add Thread.sleep(2000);
Now it works fine. Which one is a better way?
This question is related to
java
selenium
selenium-webdriver
webdriver
Thread.Sleep(5000);
This did help me but InterruptedException exception needs to be taken care of. So better surround it with try and catch:
try {
Thread.Sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
OR
Add throws declaration:
public class myClass {
public static void main(String[] args) throws InterruptedException
{ ... }
I would prefer the second one since one can then use sleep()
as many times as it wants and avoid the repetition of try
and catch
block every time wherever sleep()
has been used.
Implicit Wait: During Implicit wait if the Web Driver cannot find it immediately because of its availability, the WebDriver will wait for mentioned time and it will not try to find the element again during the specified time period. Once the specified time is over, it will try to search the element once again the last time before throwing exception. The default setting is zero. Once we set a time, the Web Driver waits for the period of the WebDriver object instance.
Explicit Wait: There can be instance when a particular element takes more than a minute to load. In that case you definitely not like to set a huge time to Implicit wait, as if you do this your browser will going to wait for the same time for every element. To avoid that situation you can simply put a separate time on the required element only. By following this your browser implicit wait time would be short for every element and it would be large for specific element.
click appears to be blocking? - here's another way to wait if you're using WebDriverJS:
driver.findElement(webdriver.By.name('mybutton')).click().then(function(){
driver.getPageSource().then(function(source) {
console.log(source);
});
});
The code above waits after the button is clicked for the next page to load and then grabs the source of the next page.
Sometimes implicit wait seems to get overridden and wait time is cut short. [@eugene.polschikov] had good documentation on the whys. I have found in my testing and coding with Selenium 2 that implicit waits are good but occasionally you have to wait explicitly.
It is better to avoid directly calling for a thread to sleep, but sometimes there isn't a good way around it. However, there are other Selenium provided wait options that help. waitForPageToLoad and waitForFrameToLoad have proved especially useful.
I prefer the following code to wait for 2 seconds.
for(int i=0; i<2 && driver.findElements(By.id("textbox")).size()==0 ; i++){
Thread.sleep(1000);
}
Thread.sleep(1000);
is the worse: being a static wait, it will make test script slower.
driver.manage().timeouts.implicitlyWait(10,TimeUnit.SECONDS);
this is a dynamic wait
Finally, what I suggest is
WebDriverWait wait = new WebDriverWait(driver,20);
wait.until(ExpectedConditions.<different canned or predefined conditions are there>);
with some predefined conditions:
isAlertPresent();
elementToBeSelected();
visibilityOfElementLocated();
visibilityOfAllElementLocatedBy();
frameToBeAvailableAndSwitchToIt();
Implicitly wait and Thread.sleep Both are used for synchronization only..but the difference is we can use Implicitly wait for entire program but Thread.sleep will works for that single code only..Here my suggestion is use Implicitly wait once in the program when every time your Webpage will get refreshed means use Thread.sleep at that time..it will much Better :)
Here is My Code :
package beckyOwnProjects;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;
public class Flip {
public static void main(String[] args) throws InterruptedException {
WebDriver driver=new FirefoxDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(2, TimeUnit.MINUTES);
driver.get("https://www.flipkart.com");
WebElement ele=driver.findElement(By.cssSelector(".menu-text.fk-inline-block"));
Actions act=new Actions(driver);
Thread.sleep(5000);
act.moveToElement(ele).perform();
}
}
Sometimes implicit wait fails, saying that an element exists but it really doesn't.
The solution is to avoid using driver.findElement and to replace it with a custom method that uses an Explicit Wait implicitly. For example:
import org.openqa.selenium.NoSuchElementException;
public WebElement element(By locator){
Integer timeoutLimitSeconds = 20;
WebDriverWait wait = new WebDriverWait(driver, timeoutLimitSeconds);
try {
wait.until(ExpectedConditions.presenceOfElementLocated(locator));
}
catch(TimeoutException e){
throw new NoSuchElementException(locator.toString());
}
WebElement element = driver.findElement(locator);
return element;
}
There are additional reasons to avoid implicit wait other than sporadic, occasional failures (see this link).
You can use this "element" method in the same way as driver.findElement. For Example:
driver.get("http://yoursite.html");
element(By.cssSelector("h1.logo")).click();
If you really want to just wait a few seconds for troubleshooting or some other rare occasion, you can create a pause method similar to what selenium IDE offers:
public void pause(Integer milliseconds){
try {
TimeUnit.MILLISECONDS.sleep(milliseconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
This thread is a bit older, but thought I'd post what I currently do (work in progress).
Though I'm still hitting situations where the system is under heavy load and when I click a submit button (e.g., login.jsp), all three conditions (see below) return true
but the next page (e.g., home.jsp) hasn't started loading yet.
This is a generic wait method that takes a list of ExpectedConditions.
public boolean waitForPageLoad(int waitTimeInSec, ExpectedCondition<Boolean>... conditions) {
boolean isLoaded = false;
Wait<WebDriver> wait = new FluentWait<>(driver)
.withTimeout(waitTimeInSec, TimeUnit.SECONDS)
.ignoring(StaleElementReferenceException.class)
.pollingEvery(2, TimeUnit.SECONDS);
for (ExpectedCondition<Boolean> condition : conditions) {
isLoaded = wait.until(condition);
if (isLoaded == false) {
//Stop checking on first condition returning false.
break;
}
}
return isLoaded;
}
I have defined various reusable ExpectedConditions (three are below). In this example, the three expected conditions include document.readyState = 'complete', no "wait_dialog" present, and no 'spinners' (elements indicating async data is being requested).
Only the first one can be generically applied to all web pages.
/**
* Returns 'true' if the value of the 'window.document.readyState' via
* JavaScript is 'complete'
*/
public static final ExpectedCondition<Boolean> EXPECT_DOC_READY_STATE = new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
String script = "if (typeof window != 'undefined' && window.document) { return window.document.readyState; } else { return 'notready'; }";
Boolean result;
try {
result = ((JavascriptExecutor) driver).executeScript(script).equals("complete");
} catch (Exception ex) {
result = Boolean.FALSE;
}
return result;
}
};
/**
* Returns 'true' if there is no 'wait_dialog' element present on the page.
*/
public static final ExpectedCondition<Boolean> EXPECT_NOT_WAITING = new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
Boolean loaded = true;
try {
WebElement wait = driver.findElement(By.id("F"));
if (wait.isDisplayed()) {
loaded = false;
}
} catch (StaleElementReferenceException serex) {
loaded = false;
} catch (NoSuchElementException nseex) {
loaded = true;
} catch (Exception ex) {
loaded = false;
System.out.println("EXPECTED_NOT_WAITING: UNEXPECTED EXCEPTION: " + ex.getMessage());
}
return loaded;
}
};
/**
* Returns true if there are no elements with the 'spinner' class name.
*/
public static final ExpectedCondition<Boolean> EXPECT_NO_SPINNERS = new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
Boolean loaded = true;
try {
List<WebElement> spinners = driver.findElements(By.className("spinner"));
for (WebElement spinner : spinners) {
if (spinner.isDisplayed()) {
loaded = false;
break;
}
}
}catch (Exception ex) {
loaded = false;
}
return loaded;
}
};
Depending on the page, I may use one or all of them:
waitForPageLoad(timeoutInSec,
EXPECT_DOC_READY_STATE,
EXPECT_NOT_WAITING,
EXPECT_NO_SPINNERS
);
There are also predefined ExpectedConditions in the following class: org.openqa.selenium.support.ui.ExpectedConditions
If using webdriverJs (node.js),
driver.findElement(webdriver.By.name('btnCalculate')).click().then(function() {
driver.sleep(5000);
});
The code above makes browser wait for 5 seconds after clicking the button.
I like to use custom conditions. Here's some code in Python:
def conditions(driver):
flag = True
ticker = driver.find_elements_by_id("textbox")
if not ticker:
flag = False
return flag
... click something to load ...
self.wait = WebDriverWait(driver, timeout)
self.wait.until(conditions)
Whenever you need to wait, you can do it explicitly by checking existance of a certain element (such element may vary from page to page). find_elements_by_id
returns list - empty or not, you have just to check.
Answer : wait for few seconds before element visibility using Selenium WebDriver go through below methods.
implicitlyWait() : WebDriver instance wait until full page load. You muse use 30 to 60 seconds to wait full page load.
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
ExplicitlyWait WebDriverWait() : WebDriver instance wait until full page load.
WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.visibilityOf(textbox));
driver.findElement(By.id("Year")).sendKeys(allKeys);
Note : Please use ExplicitlyWait WebDriverWait() to handle any particular WebElement.
Using Thread.sleep(2000);
is an unconditional wait. If your test loads faster you will still have to wait. So in principle using implicitlyWait
is the better solution.
However, I don't see why implicitlyWait
does not work in your case. Did you measure if the findElement
actually takes two seconds before throwing an exception. If so, can you try to use WebDriver's conditional wait as described in this answer?
Source: Stackoverflow.com