在测试过程中更改 Selenium 隐式等待
Changing Selenium implicit wait inside test process
我知道,根据一些意见,在完美的情况下我不应该使用隐式等待。但是我有一个慢 UI;将显式等待添加到所有可能发生渲染的地方将是一项相当大的努力。在驱动程序初始化时设置的 20 秒标准隐式等待完美覆盖了 80% 的等待时间。
但我需要处理剩下的 20%。有时我需要等待一个元素消失——在这种情况下,隐式等待意味着额外的 20 秒。有时我需要检查一个元素是否存在,而不是等待它全部 20 秒(因为在正常执行流程中通常不存在该元素)。
所以,我自然要暂时禁用隐式等待:
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
new WebDriverWait(driver, MY_TIMEOUT)).until(ExpectedConditions.WHATEVER_I_NEED);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
但这会稳定吗?或者改变隐式等待(在这种情况下,从 20 到 0 再回到 20)是否有某种危险?
如果UI很慢,添加一些服务员等待页面完全加载怎么样?以下是我为确保页面已完全加载所做的工作。
public static void waitForDomToComplete(WebDriver driver) {
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(60, TimeUnit.SECONDS)
.pollingEvery(700, TimeUnit.MILLISECONDS)
.withMessage("Time out is reached. Page is not loaded!");
wait.until(new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
JavascriptExecutor js = (JavascriptExecutor) driver;
String domLoadStatus = (String) js.executeScript("return document.readyState");
if (domLoadStatus.equals("complete")) {
return true;
} else {
return false;
}
}
});
}
完全可以做到这一点。更重要的是避免混淆隐式和显式等待的正确方法。这种混合等待会导致一些难以调试的问题,等待时间很长。问题是您可能忘记关闭和打开隐式等待。最好编写一个实用程序函数来通过传递显式等待条件来包装此逻辑,并在您的代码库中使用它。
我试着创建了一个通用的方法来使用。虽然通用不是我的强项。
protected static <T> T waitECTimeoutWrapped(WebDriver driver, ExpectedCondition<T> ec, int timeout) {
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
WebDriverWait wait = new WebDriverWait(driver, timeout);
T data = waitDriver.until(ec);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
return data;
}
在很多情况下,您可以忽略 return 数据,但这样您就可以在一次调用中检索您可能正在寻找的元素。
我知道,根据一些意见,在完美的情况下我不应该使用隐式等待。但是我有一个慢 UI;将显式等待添加到所有可能发生渲染的地方将是一项相当大的努力。在驱动程序初始化时设置的 20 秒标准隐式等待完美覆盖了 80% 的等待时间。
但我需要处理剩下的 20%。有时我需要等待一个元素消失——在这种情况下,隐式等待意味着额外的 20 秒。有时我需要检查一个元素是否存在,而不是等待它全部 20 秒(因为在正常执行流程中通常不存在该元素)。
所以,我自然要暂时禁用隐式等待:
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
new WebDriverWait(driver, MY_TIMEOUT)).until(ExpectedConditions.WHATEVER_I_NEED);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
但这会稳定吗?或者改变隐式等待(在这种情况下,从 20 到 0 再回到 20)是否有某种危险?
如果UI很慢,添加一些服务员等待页面完全加载怎么样?以下是我为确保页面已完全加载所做的工作。
public static void waitForDomToComplete(WebDriver driver) {
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(60, TimeUnit.SECONDS)
.pollingEvery(700, TimeUnit.MILLISECONDS)
.withMessage("Time out is reached. Page is not loaded!");
wait.until(new ExpectedCondition<Boolean>() {
@Override
public Boolean apply(WebDriver driver) {
JavascriptExecutor js = (JavascriptExecutor) driver;
String domLoadStatus = (String) js.executeScript("return document.readyState");
if (domLoadStatus.equals("complete")) {
return true;
} else {
return false;
}
}
});
}
完全可以做到这一点。更重要的是避免混淆隐式和显式等待的正确方法。这种混合等待会导致一些难以调试的问题,等待时间很长。问题是您可能忘记关闭和打开隐式等待。最好编写一个实用程序函数来通过传递显式等待条件来包装此逻辑,并在您的代码库中使用它。
我试着创建了一个通用的方法来使用。虽然通用不是我的强项。
protected static <T> T waitECTimeoutWrapped(WebDriver driver, ExpectedCondition<T> ec, int timeout) {
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
WebDriverWait wait = new WebDriverWait(driver, timeout);
T data = waitDriver.until(ec);
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
return data;
}
在很多情况下,您可以忽略 return 数据,但这样您就可以在一次调用中检索您可能正在寻找的元素。