Selenium WebDriverを使用して要素が存在するかどうかをテストしますか?


163

要素が存在するかどうかをテストする方法はありますか?findElementメソッドは例外で終了しますが、要素が存在しないこと、それが問題ないこと、テストの失敗ではないため、例外が解決策になることはありません。

私はこの投稿を見つけました:Selenium c#Webdriver:Wait Until Element is Present しかし、これはC#のためのものであり、私はそれがあまり得意ではありません。誰でもコードをJavaに変換できますか?申し訳ありませんが、Eclipseで試してみましたが、Javaコードでは正しく理解できません。

これはコードです:

public static class WebDriverExtensions{
    public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds){

        if (timeoutInSeconds > 0){
            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
            return wait.Until(drv => drv.FindElement(by));
        }

        return driver.FindElement(by);
    }
}

私はオブジェクトのチェックで非常に効果的に機能するいくつかのメソッドを持っていますが、それはあなたがそれをどうしたいかによって異なります。たとえば、存在するまで要素を探しますか、それが存在しなくなるまで探しますか、それとも単にそれを見つけようとしますか?
CBRRacer

1
JavaはC#に非常に似ています。ここで遭遇している主な問題の1つは、JavaのIWebElementではなくWebElementです
CBRRacer

暗黙の待機メソッドについて知っていますか?テストの開始時にこれを設定することで、要素の存在を確認する必要がなくなります。これは、暗黙の待機値を使用してポーリングするためです。ただし、その値を超えると例外がスローされます
Bob Evans

ここではJavaでWebDriverWaitについての私の記事は次のとおりです。WebDriverWait

どちらの場合も問題ない場合は、実際には存在しないはずの要素を待機するための待機時間が増えるため、これはテストのパフォーマンスにとって問題になる可能性があります。私は待ち時間を回避するためにいくつかのハックを使用しましたが、これに対する真にクリーンなソリューションをまだ見つけていません。
mrfreester 2014年

回答:


277

findElements代わりに使用しますfindElement

findElements 例外の代わりに一致する要素が見つからない場合、空のリストを返します。

要素が存在することを確認するには、これを試すことができます

Boolean isPresent = driver.findElements(By.yourLocator).size() > 0

少なくとも1つの要素が見つかった場合はtrueを返し、存在しない場合はfalseを返します。

公式ドキュメントはこの方法を推奨しています:

存在しない要素の検索にはfindElementを使用しないでください。代わりにfindElements(By)を使用して、長さゼロの応答をアサートしてください。


32
これにより、テストの実行にかかる時間が大幅に増加します。このテクニックはどこでも使用できるわけではありません。
Droogans 2012年

8
@Droogans-テストに時間をかけません。デフォルトの暗黙の待機がまだ0であるため、これが行われない理由です。デフォルトの暗黙の待機を増やした場合、同意することに同意しますが、ここではそうではありません。
djangofan 2015年

1
よろしくお願いしますdjangofan!ドライバーのタイムアウトの暗黙の待機をゼロに変更し、それを以前の値に戻すことで、この戦略をうまく使用しました。
エメリー、2015年

3
これによりNoSuchElementFound例外が発生しました。これは、特定のインスタンスでその例外をキャッチしないようにこれを使用することを望んでいたので、残念です。

1
より簡単な方法は次のようにすることです:if(driver.getPageSource()。contains( "A text in page")){}ページにこのテキストが含まれている場合、条件はtrueになります。そうでない場合はfalseになり、コードを記述できます。それに応じて。
pradyot

56

単純に要素を検索し、次のように存在するかどうかを判断するプライベートメソッドはどうでしょうか。

private boolean existsElement(String id) {
    try {
        driver.findElement(By.id(id));
    } catch (NoSuchElementException e) {
        return false;
    }
    return true;
}

これは非常に簡単で、仕事をします。

編集:By elementLocatorid以外の要素で要素を検索する場合の問題を排除するために、さらに進んでパラメーターとして受け取ることもできます。


3
うん、これは行く方法です。結果が0の場合、人々がこのように無視して、整合素子を数え、見ている理由を理解しないでください
ラルフ・ラヴェル

45
まあ、私は例外を使用してプログラムの流れを規制するのが最善の方法ではないことを言わなければなりません。
デニス

2
え?それはあなたの提案でした!テストで要素が見つからないことが予想される場合は、この方法が適しています。ご覧のとおり、nullを返し、assert.isnullまたはisnotnullを返します。これは、存在するかどうかをテストする意味のある方法です。
ラルフラヴェル2014

2
「要素が存在するかどうかをテストする方法はありますか?」という質問を誤って解釈した場合 間違っています。これが正当な答えであるかどうかについてあなたの意見が異なる理由を知って喜んでいます。
Dennis

待機時間を減らしたい場合があります。現在、要素が存在しない場合、関数がfalseを返すまで「30秒」待つ必要があります
Jason Smiley

14

これはJavaで機能することがわかりました:

WebDriverWait waiter = new WebDriverWait(driver, 5000);
waiter.until( ExpectedConditions.presenceOfElementLocated(by) );
driver.FindElement(by);

18
presenceOfElementLocated要素が特定の試行で見つからない場合は、例外がスローされます。これを回避するにはwait.ignoring(NoSuchElementException.class);、1行目と2行目の間にステートメントを追加します。
スティーブチェンバーズ

8
public static WebElement FindElement(WebDriver driver, By by, int timeoutInSeconds)
{
    WebDriverWait wait = new WebDriverWait(driver, timeoutInSeconds);
    wait.until( ExpectedConditions.presenceOfElementLocated(by) ); //throws a timeout exception if element not present after waiting <timeoutInSeconds> seconds
    return driver.findElement(by);
}

5

同じ問題がありました。私の場合、ユーザーの権限レベルによっては、一部のリンク、ボタン、およびその他の要素がページに表示されません。私のスイートの一部は、欠落しているはずの要素が欠落していることをテストしていました。私はこれを理解しようと何時間も費やしました。ようやく完璧な解決策を見つけました。

これは、指定された要素に基づいてすべての要素を探すようにブラウザに指示することです。結果がの場合0は、仕様に基づく要素が見つからなかったことを意味します。次に、コードがifステートメントを実行して、見つからなかったことを知らせます。

これはにC#あるため、に翻訳する必要がありJavaます。しかし、難しいことではありません。

public void verifyPermission(string link)
{
    IList<IWebElement> adminPermissions = driver.FindElements(By.CssSelector(link));
    if (adminPermissions.Count == 0)
    {
        Console.WriteLine("User's permission properly hidden");
    }
}

また、テストに必要なものに応じて実行できる別の方法もあります。

次のスニペットは、ページに特定の要素が存在するかどうかを確認しています。要素の存在に応じて、テストにif elseを実行させます。

要素が存在し、ページに表示されている場合、console.write私は知らせて先に進みます。問題の要素が存在する場合、必要なテストを実行できません。これは、これを設定する必要がある主な理由です。

要素が存在せず、ページに表示されない場合。if elseにelseがあり、テストを実行します。

IList<IWebElement> deviceNotFound = driver.FindElements(By.CssSelector("CSS LINK GOES HERE"));
//if the element specified above results in more than 0 elements and is displayed on page execute the following, otherwise execute whats in the else statement
if (deviceNotFound.Count > 0 && deviceNotFound[0].Displayed){
    //script to execute if element is found
} else {
    //Test script goes here.
}

OPへの対応が少し遅れていることは承知しています。うまくいけば、これは誰かを助けるでしょう!


5

これを試してください:このメソッドを呼び出して、3つの引数を渡します。

  1. WebDriver変数。// driver_variableをドライバーとして想定。
  2. チェックする要素。Byメソッドから提供する必要があります。//例:By.id( "id")
  3. 秒単位の時間制限。

例:waitForElementPresent(driver、By.id( "id")、10);

public static WebElement waitForElementPresent(WebDriver driver, final By by, int timeOutInSeconds) {

        WebElement element; 

        try{
            driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); //nullify implicitlyWait() 

            WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds); 
            element = wait.until(ExpectedConditions.presenceOfElementLocated(by));

            driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); //reset implicitlyWait
            return element; //return the element
        } catch (Exception e) {
            e.printStackTrace();
        } 
        return null; 
    }

3

try catchステートメントの前にセレンタイムアウトを短くすることで、コードをより高速に実行できます。

次のコードを使用して、要素が存在するかどうかを確認します。

protected boolean isElementPresent(By selector) {
    selenium.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
    logger.debug("Is element present"+selector);
    boolean returnVal = true;
    try{
        selenium.findElement(selector);
    } catch (NoSuchElementException e){
        returnVal = false;
    } finally {
        selenium.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
    }
    return returnVal;
}

これは私のコードで使用するものです。Seleniumのタイムアウトはデフォルトのままにして、これを使用します。
Nicholas DiPiazza

2
この回答を書いてから、ExpectedConditionsを使用する方が適切と考えられますが、要素が存在しないかどうかを確認する場合は、try catchステートメントを使用すると便利です。
EsotericNonsense

IE8をテストする必要があるため、古いバージョンのセレンに行き詰まっています。アップグレードできるときに試してみる
Nicholas DiPiazza

メソッドが暗黙の待機タイムアウトを設定するたびに、論理的には、ドライバーオブジェクトを初期化してタイムアウトをドライバーセッションに設定した後、暗黙の待機を1回だけ設定する必要があります。
Shekhar Swami

3

Javaを使用して次の関数/メソッドを記述します。

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

アサーション中に適切なパラメーターを使用してメソッドを呼び出します。


2

Rubyでrspec-Webdriverを使用している場合、このスクリプトは、要素が実際に存在してはならず、テストに合格していると想定して使用できます。

まず、このメソッドをクラスRBファイルから最初に記述します

class Test
 def element_present?
    begin
        browser.find_element(:name, "this_element_id".displayed?
        rescue Selenium::WebDriver::Error::NoSuchElementError
            puts "this element should not be present"
        end
 end

次に、スペックファイルでそのメソッドを呼び出します。

  before(:all) do    
    @Test= Test.new(@browser)
  end

 @Test.element_present?.should == nil

要素が存在しない場合、仕様は成功しますが、要素が存在する場合、エラーがスローされ、テストは失敗します。


2

これは私にとってはうまくいきます:

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

同じ問題がここに存在します:要素 "// * [@ id = 'submit']"が存在しない場合はどうなりますか?その後、例外がスローされるため、if条件が評価されない
MrBCut


1

個人的に、私は常に上記の答えを組み合わせて、size() > 0提案を使用する再利用可能な静的ユーティリティメソッドを作成します。

public Class Utility {
   ...
   public static boolean isElementExist(WebDriver driver, By by) {
      return driver.findElements(by).size() > 0;
   ...
}

これは、きちんとしていて、再利用可能で、保守可能です...すべての良いもの;-)


0

特定のElementが存在するかどうかを見つけるには、findElement()の代わりにfindElements()メソッドを使用する必要があります。

int i=driver.findElements(By.xpath(".......")).size();
if(i=0)
System.out.println("Element is not present");
else
System.out.println("Element is present");

これは私のために働いています。私が間違っているなら私に提案してください。


0

これはそれを行うはずです:

try {
    driver.findElement(By.id(id));
} catch (NoSuchElementException e) {
    //do what you need here if you were expecting
    //the element wouldn't exist
}

0

コードスニペットを提供しています。したがって、以下のメソッドは、ランダムなWeb要素の「Create New Application」ボタンがページに存在するかどうかを確認します。待機時間を0秒として使用していることに注意してください。

public boolean isCreateNewApplicationButtonVisible(){
    WebDriverWait zeroWait = new WebDriverWait(driver, 0);
    ExpectedCondition<WebElement> c = ExpectedConditions.presenceOfElementLocated(By.xpath("//input[@value='Create New Application']"));
    try {
        zeroWait.until(c);
        logger.debug("Create New Application button is visible");
        return true;
    } catch (TimeoutException e) {
        logger.debug("Create New Application button is not visible");
        return false;
    }
}

0

私は次のようなものを使用します(Scalaを使用する場合[古い「良い」Java 8のコードはこれに似ている可能性があります)):

object SeleniumFacade {

  def getElement(bySelector: By, maybeParent: Option[WebElement] = None, withIndex: Int = 0)(implicit driver: RemoteWebDriver): Option[WebElement] = {
    val elements = maybeParent match {
      case Some(parent) => parent.findElements(bySelector).asScala
      case None => driver.findElements(bySelector).asScala
    }
    if (elements.nonEmpty) {
      Try { Some(elements(withIndex)) } getOrElse None
    } else None
  }
  ...
}

それで、

val maybeHeaderLink = SeleniumFacade getElement(By.xpath(".//a"), Some(someParentElement))

0

私がJavaで見つけた最も簡単な方法は次のとおりです。

List<WebElement> linkSearch=  driver.findElements(By.id("linkTag"));
int checkLink=linkSearch.size();
if(checkLink!=0){  //do something you want}

0

暗黙の待機を試すことができます。

WebDriver driver = new FirefoxDriver();
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
driver.Url = "http://somedomain/url_that_delays_loading";
IWebElement myDynamicElement = driver.FindElement(By.Id("someDynamicElement"));

または、明示的に待機することもできます。

IWebDriver driver = new FirefoxDriver();
driver.Url = "http://somedomain/url_that_delays_loading";
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
    {
        return d.FindElement(By.Id("someDynamicElement"));
    });

Explicitは、何らかのアクションの前に要素が存在するかどうかを確認します。暗黙の待機は、コードのすべての場所で呼び出すことができます。たとえば、いくつかのAJAXアクションの後。

SeleniumHQのページで詳細を確認できます

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.