web-dev-qa-db-ja.com

WebDriver:要素が存在するかどうか確認しますか?

Webドライバに要素が存在するかどうかを確認する方法

Try catchを使用することは本当に唯一可能な方法ですか?

boolean present;
try {
   driver.findElement(By.id("logoutLink"));
   present = true;
} catch (NoSuchElementException e) {
   present = false;
}
112
Ralph

代わりにすることができます:

driver.findElements( By.id("...") ).size() != 0

これは厄介なトライ/キャッチを節約します

209
Mike Kwan

私はMikeの答えに同意しますが、オン/オフを切り替えることができる要素が見つからない場合は暗黙の3秒間待機します。これは、このアクションを頻繁に実行する場合に便利です。

driver.manage().timeouts().implicitlyWait(0, TimeUnit.MILLISECONDS);
boolean exists = driver.findElements( By.id("...") ).size() != 0
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);

たくさんのテストを実行しているのであれば、それを実用的な方法にするとパフォーマンスが向上するはずです。

48
Edd

コメントが述べているように、これはJavaではなくC#にありますが、考え方は同じです。私はこの問題を広範囲に調査しました、そして結局のところ問題は要素が存在しないときFindElementは常に例外を返すことです。 nullやその他のものを取得することを可能にするオーバーロードオプションはありません。これが私が他よりもこの解決策を好む理由です。

  1. 要素のリストを返して、リストのサイズが0かどうかを確認することはできますが、その方法では機能が失われます。コレクションのサイズが1の場合でも、リンクのコレクションに対して.click()を実行することはできません。
  2. あなたはその要素が存在すると主張することができますが、それはあなたのテストを止めます。場合によっては、そのページへのアクセス方法に応じてクリックする追加のリンクがあり、それが存在する場合はクリックし、それ以外の場合は続行します。
  3. タイムアウトを設定しないと遅くなりますdriver.Manage()。Timeouts()。ImplicitlyWait(TimeSpan.FromSeconds(0));
  4. メソッドが作成されると、それは実際には非常にシンプルでエレガントです。 FindElementの代わりにFindElementSafeを使用することで、醜いtry/catchブロックを「見る」ことはなく、単純なExistsメソッドを使用できます。これは次のようになります。

    IWebElement myLink = driver.FindElementSafe(By.Id("myId"));
    if (myLink.Exists)
    {
       myLink.Click();
    }
    

これが、IWebElementとIWebDriverを拡張する方法です。

IWebDriver.FindElementSafe

    /// <summary>
    /// Same as FindElement only returns null when not found instead of an exception.
    /// </summary>
    /// <param name="driver">current browser instance</param>
    /// <param name="by">The search string for finding element</param>
    /// <returns>Returns element or null if not found</returns>
    public static IWebElement FindElementSafe(this IWebDriver driver, By by)
    {
        try
        {
            return driver.FindElement(by);
        }
        catch (NoSuchElementException)
        {
            return null;
        }
    }

IWebElement.Exists

    /// <summary>
    /// Requires finding element by FindElementSafe(By).
    /// Returns T/F depending on if element is defined or null.
    /// </summary>
    /// <param name="element">Current element</param>
    /// <returns>Returns T/F depending on if element is defined or null.</returns>
    public static bool Exists(this IWebElement element)
    {
        if (element == null)
        { return false; }
        return true;
    }

多態性を使用してFindElementのIWebDriverクラスのインスタンスを変更することもできますが、それはメンテナンスの観点からは悪い考えです。

8

これは毎回私のために働きます:

    if(!driver.findElements(By.xpath("//*[@id='submit']")).isEmpty()){
        //THEN CLICK ON THE SUBMIT BUTTON
    }else{
        //DO SOMETHING ELSE AS SUBMIT BUTTON IS NOT THERE
    }
4
Amstel Bytes

アサーションをすることができます。

例を見てください

driver.asserts().assertElementFound("Page was not loaded",
By.xpath("//div[@id='actionsContainer']"),Constants.LOOKUP_TIMEOUT);

これはネイティブです。

public static void waitForElementToAppear(Driver driver, By selector, long timeOutInSeconds, String timeOutMessage) {
    try {
      WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
      wait.until(ExpectedConditions.visibilityOfElementLocated(selector));
    } catch (TimeoutException e) {
      throw new IllegalStateException(timeOutMessage);
    }
  }
3
Ran Adler

私はSelenium WebDriverの実装を拡張しました。私の場合はHtmlUnitDriverを使ってメソッドを公開しました。

public boolean isElementPresent(By by){}

このような:

  1. タイムアウト期間内にページがロードされたかどうかを確認してください。
  2. ページがロードされたら、WebDriverの暗黙の待ち時間を数ミリ秒、私の場合は100ミリ秒に減らします。おそらく0ミリでも動作するはずです。
  3. findElements(By)を呼び出すと、WebDriverは要素が見つからなくても上からの時間だけ待機します。
  4. 将来のページロードのための暗黙の待ち時間を遅らせる

これが私のコードです:

import Java.util.concurrent.TimeUnit;
import org.openqa.Selenium.By;
import org.openqa.Selenium.JavascriptExecutor;
import org.openqa.Selenium.WebDriver;
import org.openqa.Selenium.htmlunit.HtmlUnitDriver;
import org.openqa.Selenium.support.ui.ExpectedCondition;
import org.openqa.Selenium.support.ui.WebDriverWait;

public class CustomHtmlUnitDriver extends HtmlUnitDriver {

    public static final long DEFAULT_TIMEOUT_SECONDS = 30;
    private long timeout = DEFAULT_TIMEOUT_SECONDS;

    public long getTimeout() {
        return timeout;
    }
    public void setTimeout(long timeout) {
        this.timeout = timeout;
    }

    public boolean isElementPresent(By by) {
        boolean isPresent = true;
        waitForLoad();
        //search for elements and check if list is empty
        if (this.findElements(by).isEmpty()) {
            isPresent = false;
        }
        //rise back implicitly wait time
        this.manage().timeouts().implicitlyWait(timeout, TimeUnit.SECONDS);
        return isPresent;
    }

    public void waitForLoad() {
        ExpectedCondition<Boolean> pageLoadCondition = new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver wd) {
                //this will tel if page is loaded
                return "complete".equals(((JavascriptExecutor) wd).executeScript("return document.readyState"));
            }
        };
        WebDriverWait wait = new WebDriverWait(this, timeout);
        //wait for page complete
        wait.until(pageLoadCondition);
        //lower implicitly wait time
        this.manage().timeouts().implicitlyWait(100, TimeUnit.MILLISECONDS);
    }   
}

使用法:

CustomHtmlUnitDriver wd = new CustomHtmlUnitDriver();
wd.get("http://example.org");
if (wd.isElementPresent(By.id("Accept"))) {
    wd.findElement(By.id("Accept")).click();
}
else {
    System.out.println("Accept button not found on page");
}
2
Lotzy

Javaを使用して次のメソッドを書きます。

protected boolean isElementPresent(By by){
        try{
            driver.findElement(by);
            return true;
        }
        catch(NoSuchElementException e){
            return false;
        }
    }

アサーション中に上記のメソッドを呼び出します。

1
Ripon Al Wasim
String link = driver.findElement(By.linkText(linkText)).getAttribute("href")

これにより、要素が指しているリンクが表示されます。

1
user1549161