Java WebDriver:如何检查页面对象网络元素是否存在?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6533597/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WebDriver: How to check if an page object web element exists?
提问by Ralph
How to check if an Element exists, when using Page Objects with webdriver.
使用带有 webdriver 的页面对象时,如何检查元素是否存在。
So far I am doing it this way.
到目前为止,我是这样做的。
DefaultPage defaultPage = PageFactory.initElements(this.driver,
DefaultPage.class);
assertTrue(defaultPage.isUserCreateMenuLinkPresent());
Page Object:
页面对象:
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;
}
}
}
But I can not believe that this try/catch is the way one should do it. So what would be a better way to check if the elements exits (with using Page Objects)?
但我不敢相信这种 try/catch 是人们应该做的方式。那么有什么更好的方法来检查元素是否退出(使用页面对象)?
采纳答案by dmp
Webdriver is designed to throw an exception if an element is not found, So there aren't any methods to verify presence of an element in Webdriver.
Webdriver 旨在在未找到元素时抛出异常,因此没有任何方法可以验证 Webdriver 中元素是否存在。
Check this - http://groups.google.com/group/webdriver/browse_thread/thread/909a9b6cb568e341
检查这个 - http://groups.google.com/group/webdriver/browse_thread/thread/909a9b6cb568e341
回答by Anthony O.
Arquillianhas implemented that feature in Grapheneextension.
Arquillian已在Graphene扩展中实现了该功能。
Check ElementLocatorConditionFactory.isPresent()
function.
检查ElementLocatorConditionFactory.isPresent()
功能。
They more or less do what you wrote in your question (from ExpectedConditions.findElement
in selenium-support.jar) :
他们或多或少会做您在问题中写的内容(来自ExpectedConditions.findElement
selenium-support.jar):
try {
return driver.findElement(by);
} catch (NoSuchElementException e) {
throw e;
} catch (WebDriverException e) {
// [...] some log
throw e;
}
回答by prs
I'm using this pattern, works fine for me:
我正在使用这种模式,对我来说很好用:
public void login()
{
if (!loginButton.isDisplayed())
{
throw new IllegalStateException("Login button is not displayed!");
} else
{
loginButton.click();
}
}
or:
或者:
public boolean loginButtinIsDisplayed() {
try {
this.loginButton.getTagName();
return true;
} catch (NoSuchElementException e) {
e.printStackTrace();
return false;
}
}
回答by Flo Bayer
@Ralph: I do it the same way: try/catch. I've never found another way. You could swap out the try/catch block in a super classand design it generic. In other words: You could write a method which expects an object of type WebElement. This method contains the try/catch block and return true/false...
@Ralph:我也是这样做的:try/catch。我一直没有找到其他方法。您可以换出超类中的 try/catch 块并将其设计为generic。换句话说:您可以编写一个需要WebElement类型对象的方法。此方法包含 try/catch 块并返回 true/false...
So I wrote the following public method in the test framework's super classand am now able to use it in every page object:
所以我在测试框架的超类中编写了以下公共方法,现在可以在每个页面对象中使用它:
public boolean isElementExisting(WebElement we) {
try {
we.isDisplayed();
return true;
} catch(NoSuchElementException e) {
LOGGER.severe("Element does not exist.");
return false;
}
}
I don't know why this is not implemented in WebDriver...
我不知道为什么这没有在WebDriver 中实现......
Otherwise you could use WebDriverWait.
否则你可以使用WebDriverWait。
回答by Tarun Yaduvanshi
try this is defiantly work in pom
试试这是在 pom 中的大胆工作
public boolean isPrebuiltTestButtonVisible() {
try {
if (preBuiltTestButton.isEnabled()) {
return true;
} else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
this will definitely work in page object model surround with try catch
这肯定会在带有 try catch 的页面对象模型环绕中工作
回答by T.D.
I recently came across this old post and believe I've found one solution.
我最近遇到了这篇旧帖子,相信我已经找到了一个解决方案。
I was testing a page that had an Add User
button. When the button was clicked, various editable text fields appeared (for First Name, Last Name, Email, etc..) and a single dropdown.
我正在测试一个有Add User
按钮的页面。单击按钮时,会出现各种可编辑的文本字段(用于名字、姓氏、电子邮件等)和一个下拉列表。
When a Cancel
button was clicked, the fields disappeared and no longer existed. Using WebDriverWait
with ExpectedConditions.visibilityOf()
would not work since the elements no longer existed in the DOM
.
当Cancel
用户点击按钮时,田野里消失,不再存在。使用WebDriverWait
withExpectedConditions.visibilityOf()
将不起作用,因为元素不再存在于DOM
.
I found that @FindAll
was a solution for me, though I must admit my test ran noticeably slow at the my List assertion.
我发现这@FindAll
对我来说是一个解决方案,尽管我必须承认我的测试在我的 List 断言中运行速度明显缓慢。
For your code, something like this:
对于您的代码,如下所示:
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");}
I am able to use something similar in my own tests though, and it seems like a dependable way to skirt the 'No such element' exception. It's basically a page object adaptation of asserting: driver.findElements(By.locator).size() < 1
.
不过,我可以在自己的测试中使用类似的东西,这似乎是绕过“无此类元素”例外的可靠方法。它基本上是 asserting: 的页面对象改编driver.findElements(By.locator).size() < 1
。
回答by Андрей Шкроб
The problem is the pattern itself. It uses @FindBy annotation (used by PageFactory to init the fields that must be wrapped by Proxy) that replaces the standard elements with their proxy instances which contain InvocationHandler.
问题是模式本身。它使用@FindBy 注释(由 PageFactory 用于初始化必须由 Proxy 包装的字段)将标准元素替换为其包含 InvocationHandler 的代理实例。
Each time you try to access a field, annotated with @FindBy, the invocation handler tries to find the element using the default ElementLocator.The problem is that the ElementLocator.findElement() method throws an TimeoutException / NoSuchElementException if there are no elements presented in the DOM.
每次尝试访问一个用@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);
}
Therefore, each time you need to check whether an element is displayed or not you have to search for a List of elements and check its size.
因此,每次需要检查元素是否显示时,都必须搜索元素列表并检查其大小。
@FindBy(css = "div.custom")
private List<WebElement> elements
...
public isElementPresented(){
return elements != null && elements.size > 0
}
Another way to solve this problem is to create your own implementation of LocatingElementHandlerand ElementLocator
解决此问题的另一种方法是创建自己的LocatingElementHandler和ElementLocator 实现
So, if you need your own isDisplayed() method to return false instead of Exception, you have to replace the findElement() method in ElementLocator with something like that:
因此,如果您需要自己的 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
...
And add new conditions to LocatingElementHandler.invoke()
并向 LocatingElementHandler.invoke() 添加新条件
Something like:
就像是:
element = locator.findElement()
if(element == null){
if(method.name == "isDisplayed"){
return false
}
}
回答by Pete
Using C# bindings:
使用 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();
}
}
You're telling Selenium to grab all elements that match that Id and put them into a List of IWebElement
. You then call .Any()
on the list which evaluates to true if at least one IWebElement
was found.
您告诉 Selenium 获取与该 Id 匹配的所有元素并将它们放入IWebElement
. 然后您调用.Any()
列表,如果至少IWebElement
找到一个,则该列表评估为真。