当使用带有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;
}
}
}
但是我无法相信这种尝试/捕获是人们应该这样做的方式。 那么检查元素是否退出(使用页面对象)的更好方法是什么?
答案 0 :(得分:5)
问题在于模式本身。它使用@FindBy注释(由PageFactory用于初始化必须由Proxy包装的字段),用其包含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
}
解决此问题的另一种方法是创建自己的 LocatingElementHandler 和 ElementLocator
的实现因此,如果您需要自己的isDisplayed()方法来返回false而不是Exception,则必须使用类似的方法替换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
}
}
答案 1 :(得分:4)
如果找不到元素,Webdriver被设计为抛出异常,因此没有任何方法可以验证Webdriver中是否存在元素。
检查一下 - http://groups.google.com/group/webdriver/browse_thread/thread/909a9b6cb568e341
答案 2 :(得分: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;
}
}
答案 3 :(得分:1)
我最近遇到了这个老帖子,并且相信我找到了一个解决方案。
我正在测试一个有Add User
按钮的网页。单击该按钮时,会出现各种可编辑的文本字段(对于名字,姓氏,电子邮件等)和单个下拉列表。
单击Cancel
按钮后,字段消失,不再存在。将WebDriverWait
与ExpectedConditions.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");}
我可以在我自己的测试中使用类似的东西,但它似乎是一种可靠的方式来避免这样的元素&#39;例外。它基本上是一个页面对象改编的断言:driver.findElements(By.locator).size() < 1
。
答案 4 :(得分:1)
这是访问页面上可选元素的一个很好的模式:
@FindBy(...)
private List<WebElement> element;
public Optional<WebElement> getElement() {
return element.stream().findFirst();
}
在测试中,您可以使用以下断言:
assertEquals(Optional.empty(), page.getElement()); // element should be absent
assertTrue(page.getElement().isPresent()); // element should be present
var e = page.getElement().orElseThrow(AssertionFailedError::new); // check and use element
答案 5 :(得分:0)
Arquillian已在Graphene扩展程序中实现了该功能。
检查ElementLocatorConditionFactory.isPresent()
功能。
他们或多或少做你在问题中所写的内容(来自ExpectedConditions.findElement
in selenium-support.jar):
try {
return driver.findElement(by);
} catch (NoSuchElementException e) {
throw e;
} catch (WebDriverException e) {
// [...] some log
throw e;
}
答案 6 :(得分:0)
@Ralph :我这样做:try / catch。我从未找到另一种方式。 您可以在超类中换出try / catch块并将其设计为 generic 。换句话说:您可以编写一个期望类型为 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 。
答案 7 :(得分:0)
使用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();
}
}
您告诉Selenium要抓取与该ID匹配的所有元素,并将它们放入IWebElement
列表中。然后,如果找到至少一个.Any()
,则在列表上调用IWebElement
,评估结果为真。
答案 8 :(得分:-1)
尝试这是在pom中的挑衅
public boolean isPrebuiltTestButtonVisible() {
try {
if (preBuiltTestButton.isEnabled()) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
这肯定会在页面对象模型环绕中使用try catch