2011-06-30 41 views
16

在webdriver中使用頁面對象時如何檢查元素是否存在。WebDriver:如何檢查頁面對象Web元素是否存在?

到目前爲止,我正在這樣做。

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; 
     } 
    } 
} 

但我不能相信這個try/catch語句是一個應該做到這一點。 那麼更好的方法是檢查元素是否退出(使用頁面對象)?

+0

如果你的問題是檢查元素的可見性,這可能有所幫助:http://stackoverflow.com/questions/2646195/how-to-check-if-an-element-is-visible-with-webdriver – phtrivier

+0

@phrivier:不,這不起作用,因爲這個問題不是關於可見的,而是關於存在。 – Ralph

+0

是否可以接受由註釋注入的另一個元素(一個像root一樣存在)並使用rootELement.findElements(ByWhatever).isEmpty()? – phtrivier

回答

4

Webdriver被設計爲在未找到元素時拋出異常,所以沒有任何方法可以驗證Webdriver中元素的存在。

入住這一點 - http://groups.google.com/group/webdriver/browse_thread/thread/909a9b6cb568e341

+3

所以你的意思是:沒有辦法檢查頁面OBEJECT中是否存在Web元素,除非嘗試在可能失敗的代理上調用方法,因爲這個代理沒有實例? – Ralph

+0

雖然這可能在理論上回答這個問題,[這將是更可取的](/ meta.stackoverflow.com/q/8259)在這裏包括答案的基本部分,並提供參考鏈接。 –

1

我使用這個模式,爲我的作品罰款:

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

@Ralph:我這樣做:嘗試/捕捉。我從未找到另一種方式。 您可以換出超類中的try/catch塊並將其設計爲通用。換句話說:您可以編寫一個方法,期望類型爲WebElement的對象。這種方法包含try/catch塊,並返回真/假...

所以我在測試框架超類寫了下面的公共方法和現在能夠在每一個頁面中使用它對象

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

我不知道這是爲什麼不webdriver的實現...

否則,你可以使用WebDriverWait

+1

+1使用通用的代碼,但遺憾的是它沒有回答OP的希望,沒有使用try-catch方法。 –

+0

謝謝。那麼,我希望Selenium的人會爲此實現一個功能。但在我看來,這是目前合理的解決方案。 –

-1

嘗試,這是在挑釁POM

public boolean isPrebuiltTestButtonVisible() { 
    try { 

     if (preBuiltTestButton.isEnabled()) { 

      return true; 

     } else { 

      return false; 
     } 

    } catch (Exception e) { 

     e.printStackTrace(); 
     return false; 
    } 
} 

工作,這肯定會在頁面的對象模型的環繞嘗試捕捉工作

+0

這是關於檢查「啓用」標誌,但它會失敗,當元素不存在 - 問題是關於存在 - 抱歉。 – Ralph

+0

這使用try-catch; OP在詢問是否存在不使用try-catch的解決方案。 –

1

我最近碰到這個老帖子來了,相信我已經找到了一個解決方案。

我正在測試一個有Add User按鈕的頁面。點擊按鈕後,出現了各種可編輯的文本字段(用於名字,姓氏,電子郵件等)和一個下拉菜單。

當單擊一個Cancel按鈕時,這些字段消失並不再存在。使用WebDriverWaitExpectedConditions.visibilityOf()將不起作用,因爲元素不再存在於DOM中。

我發現@FindAll對我來說是一個解決方案,但我必須承認我的測試在我的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的頁面對象改編。

4

問題是模式本身。它使用@FindBy註釋(由PageFactory用於初始化必須由代理包裝的字段),用它們的包含InvocationHandler的代理實例替換標準元素。

每次嘗試訪問使用@FindBy註釋的字段時,調用處理程序都會嘗試使用默認的ElementLocator查找元素。問題是,如果存在,則ElementLocator.findElement()方法會引發TimeoutException/NoSuchElementException 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 
} 

解決這個問題的另一種方法是創建自己的實現LocatingElementHandlerElementLocator的

所以,如果你需要自己isDisplayed()方法返回,而不是例外假的,你必須用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 
... 

並將新條件添加到LocatingElemen tHandler。調用()

喜歡的東西:

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

當您檢查元素列表的大小時,它是否具有代理實例並計爲非空? –

+1

@EugeneS不,它將是WebElements,它是將所有元素調用重定向到ElementLocator的代理的含義。然後ElementLocator與具體的Context和WebElements進行交互 –

+0

在你的'isElementPresented()'例子中,即使沒有找到實際的元素,我也不認爲元素是'null'。它仍然是一個代理對象,不會等於'null'。 –

1

使用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(); 
    } 
} 

你告訴硒搶匹配的標識,並把它們納入到IWebElement一個列表的所有元素。然後,如果至少找到一個IWebElement,則在名單上調用.Any(),評估結果爲真。