Answers:
好吧,有两种类型的等待:显式和隐式等待。显式等待的想法是
WebDriverWait.until(condition-that-finds-the-element);
隐式等待的概念是
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
您可以在细节上有所不同 此处。
在这种情况下,我宁愿使用显式等待(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
:
等待接口的实现,可以动态配置其超时和轮询间隔。每个FluentWait实例都定义了等待条件的最长时间,以及检查条件的频率。此外,用户可以将等待配置为在等待时忽略特定类型的异常,例如在页面上搜索元素时的NoSuchElementExceptions。
您可以在这里找到详细信息
fluentWait
您的情况的用法如下:
WebElement textbox = fluentWait(By.id("textbox"));
恕我直言,这种方法更好,因为您不知道确切等待多少时间,并且可以在轮询间隔中设置任意时间值,通过该时间值可以验证元素是否存在。问候。
import com.google.common.base.Function;
,不是import java.util.function.Function;
Function
正在使用哪个。起初对我来说并不明显。感谢你的回答。
driver -> driver.findElement(locator)
。使用此方法时,您根本不需要导入语句。
.withTimeout(Duration.ofSeconds(30)).pollingEvery(Duration.ofSeconds(5))
代替: .withTimeout(30, TimeUnit.SECONDS).pollingEvery(5, TimeUnit.SECONDS)
这个线程有点旧,但是以为我会发布我目前正在做的事情(正在进行中)。
尽管我仍然遇到系统负载沉重且单击提交按钮(例如,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
);
下列类中还预定义了ExpectedConditions: org.openqa.selenium.support.ui.ExpectedConditions
如果使用webdriverJs(node.js),
driver.findElement(webdriver.By.name('btnCalculate')).click().then(function() {
driver.sleep(5000);
});
上面的代码使浏览器在单击按钮后等待5秒钟。
我喜欢使用自定义条件。这是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
返回列表-是否为空,您只需要检查即可。
隐式等待和Thread.sleep都仅用于同步..但是区别是我们可以使用隐式等待整个程序,但是Thread.sleep仅适用于单个代码。这里我的建议是在程序中使用隐式等待一次每当您的网页刷新时,意味着在那个时候使用Thread.sleep会更好:)
这是我的代码:
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();
}
}
隐式等待:在隐式等待期间,如果Web驱动程序由于可用性而无法立即找到它,则WebDriver将等待上述时间,并且在指定的时间段内它将不会尝试再次查找该元素。指定的时间结束后,它将在上一次引发异常之前尝试再次搜索元素。默认设置为零。设置时间后,Web驱动程序将等待WebDriver对象实例的时间段。
显式等待:在某些情况下,特定元素的加载可能需要一分钟以上的时间。在那种情况下,您绝对不希望为隐式等待设置大量时间,就像这样做一样,浏览器将为每个元素等待相同的时间。为了避免这种情况,您可以仅在所需元素上单独放置一个时间。通过遵循此操作,浏览器的隐式等待时间对于每个元素来说都将很短,而对于特定元素来说则将很长。
有时隐式等待失败,说一个元素存在,但实际上不存在。
解决方案是避免使用driver.findElement并将其替换为隐式使用Explicit Wait的自定义方法。例如:
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;
}
除了偶发性的偶发性故障,还有其他原因可以避免隐式等待(请参阅此链接))。
您可以以与driver.findElement相同的方式使用此“ element”方法。例如:
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();
}
}
答:等待几秒钟,然后使用Selenium WebDriver进行元素可见性检查以下方法。
hiddenlyWait():WebDriver实例等待直到整个页面加载。您需要等待30到60秒才能等待整个页面加载。
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
ExplicitlyWait WebDriverWait():WebDriver实例等待直到完整页面加载。
WebDriverWait wait = new WebDriverWait(driver, 60);
wait.until(ExpectedConditions.visibilityOf(textbox));
driver.findElement(By.id("Year")).sendKeys(allKeys);
注意:请使用ExplicitlyWait WebDriverWait()处理任何特定的WebElement。
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();
Thread.Sleep(5000);
这确实对我有所帮助,但需要注意InterruptedException异常。所以最好用try and catch包围它:
try {
Thread.Sleep(5000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
要么
添加引发声明:
public class myClass {
public static void main(String[] args) throws InterruptedException
{ ... }
我希望使用第二个,因为这样一来便可以使用任意sleep()
次数,try
并且catch
每次使用时sleep()
都避免重复和阻塞。