どのようにして Selenium 2.0がページのロードを待つようにしますか?
次のコードを使ってページロードをチェックすることもできます。
IWait<IWebDriver> wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(30.00));
wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
クラスを使用 WebDriverWait
こちら もご覧ください
あなたはいくつかの要素を表示することを期待することができます。 C#のようなもの:
WebDriver _driver = new WebDriver();
WebDriverWait _wait = new WebDriverWait(_driver, new TimeSpan(0, 1, 0));
_wait.Until(d => d.FindElement(By.Id("Id_Your_UIElement"));
ドライバの暗黙の待機を設定してから、ロードされたページにあると予想される要素に対してfindElement
メソッドを呼び出すと、WebDriverはその要素が見つかるかタイムアウト値に達するまでその要素をポーリングします。
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
ソース: 暗黙的待機
一般に、Selenium 2.0では、Webドライバはページが読み込まれたと判断した場合にのみ呼び出し側のコードに制御を返します。そうでない場合は、waitforelemement
を呼び出すことができます。これは、findelement
の呼び出しが見つかるかタイムアウトするまで循環します(タイムアウトを設定できます)。
Rubyの実装
wait = Selenium::WebDriver::Wait.new(:timeout => 10)
wait.until {
@driver.execute_script("return document.readyState;") == "complete"
}
System.out
行を削除することができます。デバッグ目的で追加されています。
WebDriver driver_;
public void waitForPageLoad() {
Wait<WebDriver> wait = new WebDriverWait(driver_, 30);
wait.until(new Function<WebDriver, Boolean>() {
public Boolean apply(WebDriver driver) {
System.out.println("Current Window State : "
+ String.valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState")));
return String
.valueOf(((JavascriptExecutor) driver).executeScript("return document.readyState"))
.equals("complete");
}
});
}
次のクラスを使用することもできます。ExpectedConditions
要素がWebページに表示されるのを明示的に待ってからアクションを実行する
ExpectedConditions
クラスを使用して、要素が可視かどうかを判断できます。
WebElement element = (new WebDriverWait(getDriver(), 10)).until(ExpectedConditions.visibilityOfElementLocated(By.cssSelector("input#houseName")));
確認できるすべての条件のリストについては、ExpectedConditions class Javadoc
を参照してください。
これらの解決策はすべて特定の場合には問題ありませんが、いくつかある可能性のある問題のうち少なくとも1つには問題があります。
それらは十分に一般的なものではありません - 彼らはあなたがこれから行おうとしているページに何らかの特定の条件が当てはまるということを前もって知ってほしいです(例えば、いくつかの要素が表示されます)
新しいページだけでなく古いページにも実際に存在する要素を使用するという競合状態に陥っています。
これは、この問題を回避する一般的な解決策(Python)を試みたものです。
まず、一般的な "wait"関数(好きならWebDriverWaitを使ってください、私はそれらが醜いと思います):
def wait_for(condition_function):
start_time = time.time()
while time.time() < start_time + 3:
if condition_function():
return True
else:
time.sleep(0.1)
raise Exception('Timeout waiting for {}'.format(condition_function.__name__))
次に、解決策はSeleniumがトップレベルの<html>
要素を含むページ上のすべての要素のための(内部)id番号を記録するという事実に頼ります。ページが更新またはロードされると、新しいIDを持つ新しいhtml要素が取得されます。
そのため、例えば "my link"というテキストのリンクをクリックしたいとします。
old_page = browser.find_element_by_tag_name('html')
browser.find_element_by_link_text('my link').click()
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
もっとPythonicの、再利用可能な、一般的なヘルパーのために、あなたはコンテキストマネージャを作ることができます:
from contextlib import contextmanager
@contextmanager
def wait_for_page_load(browser):
old_page = browser.find_element_by_tag_name('html')
yield
def page_has_loaded():
new_page = browser.find_element_by_tag_name('html')
return new_page.id != old_page.id
wait_for(page_has_loaded)
そして、Seleniumのあらゆるインタラクションでそれを使うことができます。
with wait_for_page_load(browser):
browser.find_element_by_link_text('my link').click()
それは防弾だと思います!どう思いますか?
それについての ブログ記事の詳細情報はこちら
これはWebDriverの深刻な制限のようです。明らかに要素を待ってもページがロードされることを意味するわけではありません。特に、DOMは完全にビルド(onready状態)され、それによってJSはまだ実行され、CSSとイメージはまだロードされます。
最も簡単な解決策は、すべてが初期化された後にonloadイベントでJS変数を設定し、SeleniumでこのJS変数を確認して待機することです。
Imranの答えは、Java 7について再発表されました。
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(new ExpectedCondition<Boolean>() {
public Boolean apply(WebDriver wdriver) {
return ((JavascriptExecutor) driver).executeScript(
"return document.readyState"
).equals("complete");
}
});
特定の要素がロードされるのを待ちたい場合は、RenderedWebElement
に対してisDisplayed()
メソッドを使用できます。
// Sleep until the div we want is visible or 5 seconds is over
long end = System.currentTimeMillis() + 5000;
while (System.currentTimeMillis() < end) {
// Browsers which render content (such as Firefox and IE) return "RenderedWebElements"
RenderedWebElement resultsDiv = (RenderedWebElement) driver.findElement(By.className("gac_m"));
// If results have been returned, the results are displayed in a drop down.
if (resultsDiv.isDisplayed()) {
break;
}
}
( 5分間の入門ガイドの例 )
この条件が与えられるまで、この待機で明示的に待機するか、条件付き待機します。
WebDriverWait wait = new WebDriverWait(wb, 60);
wait.until(ExpectedConditions.elementToBeClickable(By.name("value")));
これはすべてのWeb要素を60秒間待ちます。
指定された時間まで、ページ上のすべての要素の待機を暗黙的に待つことを使用します。
driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
これはすべてのWeb要素を60秒間待ちます。
指定された時間まで、ページ上のすべての要素の待機を暗黙的に待つことを使用します。
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
これは30秒間ページ上のすべての要素を待ちます。
別の待機は、指定された条件になるまで、この待機の中で明示的待機または条件付き待機です。
WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));
Idには、ページがロードされるとすぐに、ページに表示される静的要素idを指定します。
ロードするのを待っているページで、次にどの要素と対話するのかを通常知っているので、述語が最初の選択肢ではなかったことに驚きました。私のアプローチは常にwaitForElementByID(String id)
やwaitForElemetVisibleByClass(String className)
などのような述語/関数を作り、それを必要なときにいつでも使用して再利用することでした。
例えば、
私のテストクラスでは:
driverWait.until(textIsPresent("expectedText");
私のテストクラスの親では:
protected Predicate<WebDriver> textIsPresent(String text){
final String t = text;
return new Predicate<WebDriver>(){
public boolean apply(WebDriver driver){
return isTextPresent(t);
}
};
}
protected boolean isTextPresent(String text){
return driver.getPageSource().contains(text);
}
これは多くのことのように思えますが、それはあなたのために繰り返しチェックするように気を配り、チェックする頻度の間隔はタイムアウトまでの最終的な待ち時間と共に設定することができます。また、そのようなメソッドを再利用します。
この例では、親クラスがWebDriver driver
とWebDriverWait driverWait
を定義して開始しました。
これが役に立つことを願っています。
NodeJSソリューション:
Nodejsでは、promiseを介して取得できます。
あなたがこのコードを書くならば、あなたがその時に着くときあなたはページが完全にロードされていると確信することができます...
driver.get('www.sidanmor.com').then(()=> {
// here the page is fully loaded!!!
// do your stuff...
}).catch(console.log.bind(console));
このコードを書くと、ナビゲートしてSeleniumは3秒間待機します。
driver.get('www.sidanmor.com');
driver.sleep(3000);
// you can't be sure that the page is fully loaded!!!
// do your stuff... hope it will be OK...
Seleniumのドキュメントから:
this.get(url)→その後
指定されたURLにナビゲートするためのコマンドをスケジュールします。
ドキュメントの読み込みが完了したときに解決されるプロミスを返します。
SeleniumWaiter:
import com.google.common.base.Function;
import org.openqa.Selenium.By;
import org.openqa.Selenium.WebDriver;
import org.openqa.Selenium.WebElement;
import org.openqa.Selenium.support.ui.WebDriverWait;
public class SeleniumWaiter {
private WebDriver driver;
public SeleniumWaiter(WebDriver driver) {
this.driver = driver;
}
public WebElement waitForMe(By locatorname, int timeout){
WebDriverWait wait = new WebDriverWait(driver, timeout);
return wait.until(SeleniumWaiter.presenceOfElementLocated(locatorname));
}
public static Function<WebDriver, WebElement> presenceOfElementLocated(final By locator) {
// TODO Auto-generated method stub
return new Function<WebDriver, WebElement>() {
@Override
public WebElement apply(WebDriver driver) {
return driver.findElement(locator);
}
};
}
}
そしてあなたにとってそれを使ってください:
_waiter = new SeleniumWaiter(_driver);
try {
_waiter.waitForMe(By.xpath("//..."), 10);
}
catch (Exception e) {
// Error
}
以下の関数を呼び出す
public static boolean isloadComplete(WebDriver driver)
{
return ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("loaded")
|| ((JavascriptExecutor) driver).executeScript("return document.readyState").equals("complete");
}
ページのロードに20秒以上かかる場合は、以下の既存のメソッドを使用してpageeLoadTimeoutの時間を設定できます。その後、ページ再ロードの例外が発生します。
WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().pageLoadTimeout(20, TimeUnit.SECONDS)
/**
* Call this method before an event that will change the page.
*/
private void beforePageLoad() {
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("document.mpPageReloaded='notYet';");
}
/**
* Call this method after an event that will change the page.
*
* @see #beforePageLoad
*
* Waits for the previous page to disappear.
*/
private void afterPageLoad() throws Exception {
(new WebDriverWait(driver, 10)).until(new Predicate<WebDriver>() {
@Override
public boolean apply(WebDriver driver) {
JavascriptExecutor js = (JavascriptExecutor) driver;
Object obj = js.executeScript("return document.mpPageReloaded;");
if (obj == null) {
return true;
}
String str = (String) obj;
if (!str.equals("notYet")) {
return true;
}
return false;
}
});
}
ドキュメントの一部だけが変更されている場合は、ドキュメントから要素に変更できます。
このテクニックはsincebasicからの答えに触発されました。
WebDriverにJavaバインディングを使用しているときにページの読み込みを待つ最善の方法は、PageFactoryでPage Objectデザインパターンを使用することです。これはあなたがそれを置くためのAjaxElementLocatorFactory
を利用することを可能にし、単にあなたのすべての要素に対するグローバルな待ち時間として機能します。ドロップボックスや複雑なJavaScriptトランジションなどの要素には制限がありますが、必要なコード量が大幅に削減され、テスト時間が短縮されます。良い例がこのブログ投稿にあります。 Core Javaの基本的な知識があることを前提としています。
http://startingwithseleniumwebdriver.blogspot.ro/2015/02/wait-in-page-factory.html
誰かがセレン化物を使用するならば:
public static final Long SHORT_WAIT = 5000L; // 5 seconds
$("some_css_selector").waitUntil(Condition.appear, SHORT_WAIT);
より多くの条件はここで見つけることができます: http://selenide.org/javadoc/3.0/com/codeborne/selenide/Condition.html
私の簡単な方法:
long timeOut = 5000;
long end = System.currentTimeMillis() + timeOut;
while (System.currentTimeMillis() < end) {
if (String.valueOf(
((JavascriptExecutor) driver)
.executeScript("return document.readyState"))
.equals("complete")) {
break;
}
}
あなたは待つことができます。 Seleniumには、基本的に2種類の待機があります。
- 暗黙の待機
これはとても簡単です。下記の構文を見てください。
driver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
- 明示的な待機
指定された条件が発生するまで、この待機で明示的に待機または条件付き待機します。
WebDriverWait wait = new WebDriverWait(driver, 40);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));
visblityOf()
、visblityOfElement()
のような他のプロパティを使うことができます。
私の場合は、ページの読み込み状況を知るために次の方法を使用しました。私たちのアプリケーションにはgifがロードされているので、スクリプト内の不要な待ち時間を排除するために、次のようにそれらを聞きます。
public static void processing(){
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//div[@id='Msgpanel']/div/div/img")));
}
XpathがHTML DOM内のgifを見つける場所。この後、あなたはまたあなたのアクションメソッドClickを実装することができます。
public static void click(WebElement elementToBeClicked){
WebDriverWait wait = new WebDriverWait(driver, 45);
wait.until(ExpectedConditions.visibilityOf(element));
wait.until(ExpectedConditions.elementToBeClickable(element));
wait.ignoring(NoSuchElementException.class).ignoring(StaleElementReferenceException.class); elementToBeClicked.click();
}
(element.click()のように)アクションを実行する前に、Webページに要素が表示されるのを明示的に待つことができます。
driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = (new WebDriverWait(driver, 10))
.until(new ExpectedCondition<WebElement>(){
@Override
public WebElement apply(WebDriver d) {
return d.findElement(By.id("myDynamicElement"));
}});
これは私が似たようなシナリオで使ったもので、うまくいきます。
このコードスニペットを使用して、ページを読み込むことができます。
IWait wait = new OpenQA.Selenium.Support.UI.WebDriverWait(driver,TimeSpan.FromSeconds(30.00));
wait.Until(driver1 => ((IJavaScriptExecutor)driver).ExecuteScript("return document.readyState").Equals("complete"));
あるいは、任意の要素をロードしてそのページで表示/クリックできるようにするためにwaiterを使用することもできます。おそらく、ロード終了時にロードされることになるでしょう。
Wait.Until(ExpectedConditions.ElementToBeClickable(By.XPath(xpathOfElement));
var element = GlobalDriver.FindElement(By.XPath(xpathOfElement));
var isSucceededed = element != null;
これは現在 最も支持されている答え のJava 8バージョンです。
WebDriverWait wait = new WebDriverWait(myDriver, 15);
wait.until(webDriver -> ((JavascriptExecutor) myDriver).executeScript("return document.readyState").toString().equals("complete"));
myDriver
はWebDriver
オブジェクト(以前に宣言されたもの)です。
注:このメソッド(document.readyState
)はDOMのみをチェックすることに注意してください。
私が見た最善の方法は、古いページが古くなるのを待つためにstalenessOf
ExpectedConditionを利用することです。
例:
WebDriver driver = new FirefoxDriver();
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement oldHtml = driver.findElement(By.tagName("html"));
wait.until(ExpectedConditions.stalenessOf(oldHtml));
古いHTMLタグが古くなるのを10秒間待ってから、そうでない場合は例外をスローします。
私はnode + Selenium-webdriver(現在のバージョンは3.5.0)を使います。私はこれのために何をしますか:
var webdriver = require('Selenium-webdriver'),
driver = new webdriver.Builder().forBrowser('chrome').build();
;
driver.wait(driver.executeScript("return document.readyState").then(state => {
return state === 'complete';
}))
暗黙的に待つ場合は、次のようなものを使用できます。
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS)
Webページが特定のオブジェクトが表示されるまで、または特定の条件が満たされるのを待つために。あなたはWebドライバの待機羽根を使うことができます。
//120 is maximum number of seconds to wait.
WebDriverWait wait = new WebDriverWait(driver,120);
wait.until(ExpectedConditions.elementToBeClickable("CONDITITON"));
Javaでは、スレッドを特定の時間だけスリープさせることもできます。
Thread.sleep(numberOfSeconds*1000);
//This line will cause thread to sleep for seconds as variable
Thread.sleepメソッドを単純化するためのメソッドを作成しました
public static void wait_time(int seconds){
try {
Thread.sleep(seconds*1000);
}catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
メソッドをwait_time(10)として使用してください。スレッドは10秒間スリープします。
クリック後にSeleniumにページロードを待機させる方法は、次のような興味深いアプローチを提供します。
WebElement
への参照を保存します。WebElement
がスローされるまで、StaleElementReferenceException
に対して操作を呼び出し続けます。サンプルコード
WebElement link = ...;
link.click();
new WebDriverWait(webDriver, timeout).until((org.openqa.Selenium.WebDriver input) ->
{
try
{
link.isDisplayed();
return false;
}
catch (StaleElementReferenceException unused)
{
return true;
}
});
private static void checkPageIsReady(WebDriver driver) {
JavascriptExecutor js = (JavascriptExecutor) driver;
// Initially bellow given if condition will check ready state of page.
if (js.executeScript("return document.readyState").toString().equals("complete")) {
System.out.println("Page Is loaded.");
return;
}
// This loop will rotate for 25 times to check If page Is ready after
// every 1 second.
// You can replace your value with 25 If you wants to Increase or
// decrease wait time.
for (int i = 0; i < 25; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
// To check page ready state.
if (js.executeScript("return document.readyState").toString().equals("complete")) {
break;
}
}
}
public static int counter = 0;
public void stepGeneralWait() {
boolean breakIt = true;
while (true) {
breakIt = true;
try {
do{
// here put e.g. your spinner ID
Controller.driver.findElement(By.xpath("//*[@id='static']/div[8]/img")).click();
Thread.sleep(10000);
counter++;
if (counter > 3){
breakIt = false;
}
}
while (breakIt);
} catch (Exception e) {
if (e.getMessage().contains("element is not attached")) {
breakIt = false;
}
}
if (breakIt) {
break;
}
}
try {
Thread.sleep(12000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
このコードを試して、要素が見つかるまでページを完全に読み込ませることができます。
public void waitForBrowserToLoadCompletely() {
String state = null;
String oldstate = null;
try {
System.out.print("Waiting for browser loading to complete");
int i = 0;
while (i < 5) {
Thread.sleep(1000);
state = ((JavascriptExecutor) driver).executeScript("return document.readyState;").toString();
System.out.print("." + Character.toUpperCase(state.charAt(0)) + ".");
if (state.equals("interactive") || state.equals("loading"))
break;
/*
* If browser in 'complete' state since last X seconds. Return.
*/
if (i == 1 && state.equals("complete")) {
System.out.println();
return;
}
i++;
}
i = 0;
oldstate = null;
Thread.sleep(2000);
/*
* Now wait for state to become complete
*/
while (true) {
state = ((JavascriptExecutor) driver).executeScript("return document.readyState;").toString();
System.out.print("." + state.charAt(0) + ".");
if (state.equals("complete"))
break;
if (state.equals(oldstate))
i++;
else
i = 0;
/*
* If browser state is same (loading/interactive) since last 60
* secs. Refresh the page.
*/
if (i == 15 && state.equals("loading")) {
System.out.println("\nBrowser in " + state + " state since last 60 secs. So refreshing browser.");
driver.navigate().refresh();
System.out.print("Waiting for browser loading to complete");
i = 0;
} else if (i == 6 && state.equals("interactive")) {
System.out.println(
"\nBrowser in " + state + " state since last 30 secs. So starting with execution.");
return;
}
Thread.sleep(4000);
oldstate = state;
}
System.out.println();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
最も簡単な方法は、読み込まれたページに表示される要素を待つことです。
ページがロードされた後にすでに何らかのボタンをクリックしたい場合は、awaitを使用してクリックすることができます。
await().until().at.most(20, TimeUnit.Seconds).some_element.isDisplayed(); // or another condition
getDriver().find(some_element).click;
次のコードを使用すると、ページを簡単にロードできます。
public void PageLoad(IWebDriver driver, By by)
{
try
{
Console.WriteLine("PageLoad" + by);
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30));
wait.Until(ExpectedConditions.ElementIsVisible(by));
wait = new WebDriverWait(driver, TimeSpan.FromSeconds(30)); // 30 seconds wait until element not found.
wait.Until(ExpectedConditions.ElementToBeClickable(by));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
Assert.Fail("Element not found!")
}
}
これがお役に立てば幸いです。
WebDriver driver = new ff / chrome / anyDriverYouWish(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
最大10秒待ちます。
WebDriverWait wait = new WebDriverWait(driver, 10); wait.until(ExpectedConditions.visibilityOf(WebElement element));
FluentWait<Driver> fluentWait; fluentWait = new FluentWait<>(driver).withTimeout(30, TimeUnit.SECONDS) .pollingEvery(200, TimeUnit.MILLISECONDS) .ignoring(NoSuchElementException.class);
最後のオプションの利点は、予想される例外を含めることができるため、実行が継続されることです。
driver.asserts().assertElementFound("Page was not loaded",
By.xpath("//div[@id='actionsContainer']"),Constants.LOOKUP_TIMEOUT);
if条件を使用し、存在する任意の要素に
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}