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

但我无法相信这种尝试/捕获是人们应该这样做的方式。 那么什么是更好的方法来检查元素是否退出(使用页面对象)?

如果找不到元素,Webdriver被设计为抛出exception,因此没有任何方法可以validationWebdriver中是否存在元素。

检查一下 – http://groups.google.com/group/webdriver/browse_thread/thread/909a9b6cb568e341

问题在于模式本身。 它使用@FindBy批注(由PageFactory用于初始化必须由Proxy包装的字段),用其包含InvocationHandler的代理实例替换标准元素。

每次尝试访问使用@FindBy注释的字段时,调用处理程序都会尝试使用默认的ElementLocator查找元素。问题是如果没有元素,则ElementLocator.findElement()方法会抛出TimeoutException / NoSuchElementException。 DOM。

 public WebElement findElement(SearchContext context) { List 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 elements ... public isElementPresented(){ return elements != null && elements.size > 0 } 

解决此问题的另一种方法是创建自己的LocatingElementHandlerElementLocator实现

因此,如果您需要自己的isDisplayed()方法来返回false而不是Exception,则必须使用以下内容替换ElementLocator中的findElement()方法:

 ... List elements = searchContext.findElements(by) if(elements != null && elements.size() > 0){ List 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 } } 

我正在使用这种模式,对我来说很好用:

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

我最近遇到了这个老post,并且相信我找到了一个解决方案。

我正在测试一个有“ Add User按钮的页面。 单击该按钮时,会出现各种可编辑的文本字段(对于名字,姓氏,电子邮件等)和单个下拉列表。

单击“ Cancel按钮后,字段消失,不再存在。 将WebDriverWaitExpectedConditions.visibilityOf()将不起作用,因为DOM不再存在这些元素。

我发现@FindAll对我来说是一个解决方案,不过我必须承认我的测试在我的List断言中运行得非常慢。

对于您的代码,这样的事情:

 public class DefaultPage { @FindAll({@FindBy(id = "link_i_user_create")}) List userCreateMenuLink; public boolean isUserCreateMenuLinkPresent() { if (this.userCreateMenuLink.isEmpty()) fail("Link does not exist");} 

我可以在我自己的测试中使用类似的东西,但它似乎是一种可靠的方式来绕过“没有这样的元素”的例外。 它基本上是一个页面对象改编的断言: driver.findElements(By.locator).size() < 1

Arquillian在石墨烯扩展中实现了这一function。

检查ElementLocatorConditionFactory.isPresent()函数。

他们或多或少地做你在问题中写的内容(来自selenium-support.jar中的ExpectedConditions.findElement ):

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

@Ralph :我这样做:try / catch。 我从未找到另一种方式。 您可以在超类中交换try / catch块并将其设计为通用 。 换句话说:您可以编写一个期望WebElement类型的对象的方法。 此方法包含try / catch块并返回true / false …

所以我在测试框架超类中编写了以下公共方法,现在我可以在每个页面对象中使用它:

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

我不知道为什么在WebDriver中没有实现这个…

否则你可以使用WebDriverWait

使用C#绑定:

 using System.Collections.Generic; using System.Linq; public class DefaultPage { [FindsBy(How = How.Id, Using = "link_i_user_create")] private IList userCreateMenuLink; public bool isUserCreateMenuLinkPresent() { return userCreateMenuLink.Any(); } } 

您告诉Selenium获取与该Id匹配的所有元素并将它们放入IWebElement列表中。 然后,如果找到至少一个IWebElement ,则在列表上调用.Any() ,其值为true。

试试这是在pom中的挑衅

 public boolean isPrebuiltTestButtonVisible() { try { if (preBuiltTestButton.isEnabled()) { return true; } else { return false; } } catch (Exception e) { e.printStackTrace(); return false; } } 

这肯定会在页面对象模型环绕中使用try catch