我如何让Selenium-WebDriver在Java中等待几秒钟?
我正在研究一个Java Selenium-WebDriver。 我补充说
driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);
和
WebElement textbox = driver.findElement(By.id("textbox"));
因为我的应用程序需要几秒钟来加载用户界面。 所以我设置了2秒implicitwait。 但我无法find元素文本框
然后我添加Thread.sleep(2000);
现在它工作正常。 哪一个更好?
那么有两种types的等待:显式和隐式等待。 明确的等待的想法是
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
函数返回find的Web元素。 从fluentWait
上的文档: 一个Wait接口的实现,它可以在运行中configuration超时和轮询间隔。 每个FluentWait实例定义等待条件的最大时间量以及检查条件的频率。 此外,用户可以configuration等待,以在等待时忽略特定types的exception,例如在页面上search元素时的NoSuchElementExceptions。 详细你可以在这里
在你的情况下使用fluentWait
如下:
WebElement textbox = fluentWait(By.id("textbox"));
这种方法恕我直言更好,因为你不知道到底有多less时间等待,并在轮询间隔,你可以设置任意的时间值,哪些元素的存在将通过validation。 问候。
如果使用webdriverJs(node.js),
driver.findElement(webdriver.By.name('btnCalculate')).click().then(function() { driver.sleep(5000); });
上面的代码使浏览器在点击button后等待5秒钟。
这个线程有点老,但是我以为我会发布我目前正在做的(工作正在进行)。
虽然我仍然遇到系统负载过重的情况,当我点击一个提交button(例如,login.jsp),所有三个条件(见下文)返回true
但下一页(例如,home.jsp)hasn还没有开始加载。
这是一个通用的等待方法,它采用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'(指示正在请求asynchronous数据的元素)。
只有第一个可以统一应用于所有的网页。
/** * 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
使用Thread.sleep(2000);
是无条件的等待。 如果你的testing加载得更快,你仍然需要等待。 所以原则上implicitlyWait
是更好的解决scheme。
但是,我不明白为什么implicitlyWait
你的情况不起作用。 如果findElement
实际上在抛出exception之前需要两秒钟,您是否测量过? 如果是这样,你可以尝试使用WebDriver的有条件的等待在这个答案中描述?
我喜欢使用自定义条件。 以下是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
返回列表 – 空或不,你只需要检查。
点击显示是阻止? – 如果您使用WebDriverJS,另一种方法是等待:
driver.findElement(webdriver.By.name('mybutton')).click().then(function(){ driver.getPageSource().then(function(source) { console.log(source); }); });
上面的代码等待点击button后下一页加载,然后抓取下一页的来源。
有时,隐含的等待似乎被覆盖,等待时间缩短。 [@ eugene.polschikov]有很好的文件。 我发现在我的testing和编码与selenium2隐含的等待是好的,但偶尔你必须等待明确。
最好避免直接呼吁线程睡觉,但有时候并没有一个好方法。 不过,还有其他的Selenium提供了一些有用的选项。 waitForPageToLoad和waitForFrameToLoadcertificate特别有用。
隐式地等待和Thread.sleep两者只用于同步..但不同的是,我们可以使用隐式等待整个程序,但Thread.sleep将只为单一的代码工作..这里我的build议是使用在程序中隐式等待一次当每次你的网页将得到刷新意味着使用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驱动程序由于其可用性而不能立即find它,则WebDriver将等待提及的时间,并且在指定的时间段内不会再次尝试find该元素。 一旦指定的时间结束,它将尝试在抛出exception之前再次search元素。 默认设置是零。 一旦我们设定了一段时间,Web Driver将等待WebDriver对象实例的时间。
显式等待:可能有一个特定元素需要超过一分钟才能加载的实例。 在这种情况下,你绝对不喜欢设置一个很大的时间来隐式等待,就像你这样做你的浏览器将等待每个元素的同一时间。 为了避免这种情况,你可以简单地把一个单独的时间放在所需的元素上。 通过遵循这个你的浏览器隐含的等待时间会缩短每个元素,它将是特定的元素大。
有时隐含的等待失败,说一个元素存在,但它确实没有。
解决方法是避免使用driver.findElement,并用隐式使用Explicit Wait的自定义方法replace它。 例如:
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();
如果您真的只想等待几秒钟来排除故障或其他罕见的情况,您可以创build一个类似于selenium IDE提供的暂停方法:
public void pause(Integer milliseconds){ try { TimeUnit.MILLISECONDS.sleep(milliseconds); } catch (InterruptedException e) { e.printStackTrace(); } }
我更喜欢下面的代码等待2秒钟。
for(int i=0; i<2 && driver.findElements(By.id("textbox")).size()==0 ; i++){ Thread.sleep(1000); }
public static void waitForElement(WebDriver driver)throws Exception { driver.findElement(By.xpath("//table")).sendKeys //line1(org.openqa.selenium.Keys.CONTROL); Thread.sleep(500); }
如果在更改同一页面内的一个input字段到另一个input字段的控件时页面刷新,请使用此代码。 将相应的驱动程序引用传递给此方法以查找元素。 Line1用于在外部进行刷新。 如果您有任何疑问请发表您的评论。