我正在开发Java Selenium-WebDriver。我添加了
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
和
WebElement textbox = driver.findElement(By.id("textbox"));
因为我的应用程序需要几秒钟才能加载用户界面。所以我设置2秒implicitwait。但我无法找到元素文本框
然后我添加Thread.sleep(2000);
现在它运作正常。哪一种更好?
答案 0 :(得分:111)
嗯,有两种类型的等待:显式和隐式等待。 明确等待的想法是
WebDriverWait.until(condition-that-finds-the-element);
隐式等待的概念是
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
您可以获得详细信息here。
在这种情况下,我更喜欢使用显式等待(特别是fluentWait
):
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;
};
fluentWait
函数返回找到的web元素。
来自fluentWait
的文档:
Wait接口的实现,可以动态配置其超时和轮询间隔。
每个FluentWait实例定义等待条件的最大时间量,以及检查条件的频率。此外,用户可以将等待配置为在等待时忽略特定类型的异常,例如在页面上搜索元素时的NoSuchElementExceptions。
您可以获得详细信息here
在您的案例中使用fluentWait
如下:
WebElement textbox = fluentWait(By.id("textbox"));
这种方法恕我直言更好,因为您不知道确切等待多长时间,并且在轮询间隔中您可以设置任意时间值,哪些元素存在将通过验证。 问候。
答案 1 :(得分:16)
如果使用webdriverJs(node.js),
driver.findElement(webdriver.By.name('btnCalculate')).click().then(function() {
driver.sleep(5000);
});
上面的代码使浏览器在点击按钮后等待5秒钟。
答案 2 :(得分:12)
这个帖子有点老了,但我想我会发布我目前正在做的事情(正在进行中)。
虽然我仍然遇到系统负载过重的情况,但当我点击提交按钮(例如,login.jsp)时,所有三个条件(见下文)都会返回true
但下一页(例如,home.jsp)尚未开始加载。
这是一个通用的等待方法,它采用了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;
}
我定义了各种可重复使用的ExpectedConditions(下面三个)。在此示例中,三个预期条件包括document.readyState ='complete',没有“wait_dialog”,并且没有'spinners'(表示正在请求异步数据的元素)。
只有第一个可以通用地应用于所有网页。
/**
* 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;
}
};
根据页面的不同,我可能会使用其中一个或全部:
waitForPageLoad(timeoutInSec,
EXPECT_DOC_READY_STATE,
EXPECT_NOT_WAITING,
EXPECT_NO_SPINNERS
);
以下类中还预定义了ExpectedCondition:org.openqa.selenium.support.ui.ExpectedConditions
答案 3 :(得分:9)
使用Thread.sleep(2000);
是无条件等待。如果你的测试加载速度更快,你仍然需要等待。所以原则上使用implicitlyWait
是更好的解决方案。
但是,我不明白为什么implicitlyWait
在您的情况下不起作用。您是否在测量异常之前测量findElement
是否实际需要两秒钟。如果是这样,您是否可以尝试使用WebDriver的条件等待,如this回答中所述?
答案 4 :(得分:3)
我喜欢使用自定义条件。这是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)
每当您需要等待时,您可以通过检查某个元素的存在来明确地执行此操作(此元素可能因页面而异)。 find_elements_by_id
返回列表 - 是否为空,您只需要检查。
答案 5 :(得分:2)
点击似乎是阻止? - 如果你正在使用WebDriverJS,这是另一种等待方式:
driver.findElement(webdriver.By.name('mybutton')).click().then(function(){
driver.getPageSource().then(function(source) {
console.log(source);
});
});
上面的代码在单击按钮以下载页面后等待,然后抓取下一页的来源。
答案 6 :(得分:0)
有时隐式等待似乎被覆盖,等待时间缩短。 [@ eugene.polschikov]有关于为什么的好文档。我在Selenium 2的测试和编码中发现,隐式等待是好的,但偶尔你必须明确等待。
最好避免直接调用线程进入睡眠状态,但有时候没有好办法解决问题。但是,还有其他Selenium提供的等待选项可以提供帮助。事实证明 waitForPageToLoad 和 waitForFrameToLoad 特别有用。
答案 7 :(得分:0)
隐式等待:在隐式等待期间,如果Web驱动程序因其可用性而无法立即找到它,则WebDriver将等待上述时间,并且不会尝试在指定时间段内再次找到该元素。一旦指定的时间结束,它将尝试在抛出异常之前最后一次搜索该元素。默认设置为零。设置时间后,Web驱动程序将等待WebDriver对象实例的句点。
显式等待:可能存在特定元素加载超过一分钟的实例。在这种情况下,你绝对不喜欢为Implicit wait设置一个巨大的时间,就好像你这样做,你的浏览器将等待每个元素的同一时间。 为避免这种情况,您只需在所需元素上单独设置一个时间即可。通过遵循这一点,您的浏览器隐含的等待时间对于每个元素都是短的,并且对于特定元素它将是大的。
答案 8 :(得分:0)
有时隐式等待失败,说一个元素存在但实际上并不存在。
解决方案是避免使用driver.findElement并将其替换为隐式使用显式等待的自定义方法。例如:
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;
}
除了零星的,偶然的失败之外,还有其他理由可以避免隐性等待(见link)。
您可以像driver.findElement一样使用此“元素”方法。 例如:
driver.get("http://yoursite.html");
element(By.cssSelector("h1.logo")).click();
如果你真的想等待几秒钟进行故障排除或其他一些罕见的场合,你可以创建一个类似于selenium IDE提供的暂停方法:
public void pause(Integer milliseconds){
try {
TimeUnit.MILLISECONDS.sleep(milliseconds);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
答案 9 :(得分:0)
回答:在使用Selenium WebDriver查看元素可见性之前,请等待几秒钟。
implicitlyWait():WebDriver实例等到整页加载。你冥想使用30至60秒等待整页加载。
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
显式地等待WebDriverWait():WebDriver实例等到整页加载。
WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.visibilityOf(textbox));
driver.findElement(By.id("Year")).sendKeys(allKeys);
注意:请使用ExplicitlyWait WebDriverWait()来处理任何特定的WebElement。
答案 10 :(得分:0)
答案 11 :(得分:-1)
我更喜欢以下代码等待2秒。
for(int i=0; i<2 && driver.findElements(By.id("textbox")).size()==0 ; i++){
Thread.sleep(1000);
}
答案 12 :(得分:-1)
Thread.sleep(1000);
更糟糕的是:作为静态等待,它会使测试脚本变慢。
driver.manage().timeouts.implicitlyWait(10,TimeUnit.SECONDS);
这是一次动态等待
最后,我的建议是
WebDriverWait wait = new WebDriverWait(driver,20);
wait.until(ExpectedConditions.<different canned or predefined conditions are there>);
有一些预定义的条件:
isAlertPresent();
elementToBeSelected();
visibilityOfElementLocated();
visibilityOfAllElementLocatedBy();
frameToBeAvailableAndSwitchToIt();
答案 13 :(得分:-1)
Thread.Sleep(5000);
这对我有帮助,但需要处理InterruptedException异常。 所以用try和catch更好地包围它:
try {
Thread.Sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
OR
添加投掷声明:
public class myClass {
public static void main(String[] args) throws InterruptedException
{ ... }
我更喜欢第二个,因为人们可以根据需要多次使用sleep()
,并且每次try
时都避免重复catch
和sleep()
阻止已被使用。