web-dev-qa-db-ja.com

WebDriver:ページオブジェクトのWeb要素が存在するかどうかを確認する方法

Webdriverでページオブジェクトを使用するときに、要素が存在するかどうかを確認する方法。

これまでのところ、私はこのようにしています。

DefaultPage defaultPage = PageFactory.initElements(this.driver,
      DefaultPage.class);
assertTrue(defaultPage.isUserCreateMenuLinkPresent());

ページオブジェクト:

public class DefaultPage {     
    @FindBy(id = "link_i_user_create")
    private WebElement userCreateMenuLink;


    public boolean isUserCreateMenuLinkPresent() {
        try {
            this.userCreateMenuLink.getTagName();
            return true;
        } catch (NoSuchElementException e) {
            return false;
        }
    }
 }

しかし、私はこのトライ/キャッチが人がそれを行うべき方法であるとは信じられません。 (ページオブジェクトを使用して)要素が存在するかどうかを確認するより良い方法は何ですか?

20
Ralph

Webdriverは、要素が見つからない場合に例外をスローするように設計されているため、Webdriverに要素が存在することを確認する方法はありません。

これを確認してください- http://groups.google.com/group/webdriver/browse_thread/thread/909a9b6cb568e341

4
dmp

問題はパターンそのものです。標準要素をInvocationHandlerを含むプロキシインスタンスで置き換える@FindByアノテーション(Proxyでラップする必要があるフィールドを初期化するためにPageFactoryで使用)を使用します。

@FindByで注釈が付けられたフィールドにアクセスしようとするたびに、呼び出しハンドラーはデフォルトのElementLocatorを使用して要素を見つけようとします。 DOM。

public WebElement findElement(SearchContext context) {
   List<WebElement> allElements = findElements(context);
   if (allElements == null || allElements.isEmpty())
      throw new NoSuchElementException("Cannot locate an element using "
      + toString());
   return allElements.get(0);
}

したがって、要素が表示されているかどうかを確認する必要があるたびに、要素のリストを検索してそのサイズを確認する必要があります。

@FindBy(css = "div.custom")
private List<WebElement> elements
...

public isElementPresented(){
   return elements != null && elements.size > 0
}

この問題を解決する別の方法は、LocatingElementHandlerおよびElementLocatorの独自の実装を作成することです

したがって、独自のisDisplayed()メソッドでExceptionの代わりにfalseを返す必要がある場合は、ElementLocatorのfindElement()メソッドを次のようなものに置き換える必要があります。

...
List<WebElement> elements = searchContext.findElements(by)
if(elements != null && elements.size() > 0){
   List<WebElement> visibleElements = []
   elements.each {
      if(it.displayed){
         visibleElements.add(it)
      }
   }
   if(visibleElements.size() > 0){
      return visibleElements.get(0)
   }
}
return null
...

そして、LocatingElementHandler.invoke()に新しい条件を追加します

何かのようなもの:

element = locator.findElement()
if(element == null){
   if(method.name == "isDisplayed"){
      return false
   }
}

@ Ralph:私は同じようにやってみます:try/catch。私は別の方法を見つけたことがありません。 スーパークラスのtry/catchブロックを交換して、それを設計することができますgeneric。つまり、タイプWebElementのオブジェクトを期待するメソッドを記述できます。このメソッドには、try/catchブロックが含まれ、true/falseを返します...

test frameworksuper classで次のパブリックメソッドを記述し、すべてのページオブジェクト

public boolean isElementExisting(WebElement we) {
    try {
        we.isDisplayed();
        return true;
    } catch(NoSuchElementException e) {
        LOGGER.severe("Element does not exist.");
        return false;
    }
}

これがWebDriverに実装されていない理由がわかりません...

それ以外の場合は、WebDriverWaitを使用できます。

1
Flo Bayer

私は最近この古い投稿に出くわし、1つの解決策を見つけたと信じています。

_Add User_ボタンのあるページをテストしていました。ボタンをクリックすると、さまざまな編集可能なテキストフィールド(名、姓、電子メールなど)と単一のドロップダウンが表示されました。

Cancelボタンをクリックすると、フィールドが非表示になり、存在しなくなりました。 WebDriverWaitExpectedConditions.visibilityOf()とともに使用すると、要素がDOMに存在しなくなったため機能しません。

_@FindAll_が解決策であることがわかりましたが、my Listアサーションでテストの実行が著しく遅くなったことを認めなければなりません。

あなたのコードでは、このようなもの:

_public class DefaultPage {     
@FindAll({@FindBy(id = "link_i_user_create")}) List<WebElement> userCreateMenuLink;


public boolean isUserCreateMenuLinkPresent() {
    if (this.userCreateMenuLink.isEmpty()) fail("Link does not exist");}
_

私自身のテストでも似たようなものを使用できますが、「そのような要素はありません」という例外を回避するための信頼できる方法のようです。これは基本的に、アサートのページオブジェクト適応です:driver.findElements(By.locator).size() < 1

1
T.D.

私はこのパターンを使用していますが、うまくいきます:

public void login() 
{
    if (!loginButton.isDisplayed())
    {
        throw new IllegalStateException("Login button is not displayed!");
    } else
    {
        loginButton.click();    
    }        
}

または:

public boolean loginButtinIsDisplayed() {
    try {
        this.loginButton.getTagName();
        return true;
    } catch (NoSuchElementException e) {
        e.printStackTrace();
        return false;
    }
}
1
prs

C#バインディングの使用:

_using System.Collections.Generic;
using System.Linq;

public class DefaultPage 
{
    [FindsBy(How = How.Id, Using = "link_i_user_create")]
    private IList<IWebElement> userCreateMenuLink;

    public bool isUserCreateMenuLinkPresent()
    {
        return userCreateMenuLink.Any();
    }
}
_

そのIdに一致するすべての要素を取得し、それらをIWebElementのリストに入れるようにSeleniumに指示しています。次に、少なくとも1つのIWebElementが見つかった場合にtrueと評価されるリストで.Any()を呼び出します。

0
Pete

ArquillianGraphene 拡張でその機能を実装しました。

チェック ElementLocatorConditionFactory.isPresent() 関数。

彼らは多かれ少なかれ、あなたがあなたの質問に書いたことを行います(Selenium-support.jarの ExpectedConditions.findElementから ):

try {
    return driver.findElement(by);
} catch (NoSuchElementException e) {
    throw e;
} catch (WebDriverException e) {
    // [...] some log
    throw e;
}
0
Anthony O.