2011-06-30 68 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(),评估结果为真。