it-swarm.com.ru

WebDriver: Как проверить, существует ли веб-элемент объекта страницы?

Как проверить, существует ли Элемент, при использовании Page Objects с 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;
        }
    }
 }

Но я не могу поверить, что эта попытка/улов - это способ, которым нужно это делать. Так что будет лучшим способом проверить, если элементы выходят (с использованием объектов Page)?

18
Ralph

Webdriver предназначен для создания исключения, если элемент не найден, поэтому нет никаких способов проверить наличие элемента в Webdriver.

Проверьте это - http://groups.google.com/group/webdriver/browse_thread/thread/909a9b6cb568e341

4
dmp

Проблема в самом шаблоне. Он использует аннотацию @FindBy (используется PageFactory для инициализации полей, которые должны быть упакованы прокси-сервером), которая заменяет стандартные элементы их экземплярами прокси-сервера, которые содержат InvocationHandler.

Каждый раз, когда вы пытаетесь получить доступ к полю, аннотированному @FindBy, обработчик вызова пытается найти элемент, используя ElementLocator по умолчанию. Проблема заключается в том, что метод ElementLocator.findElement () генерирует исключение TimeoutException/NoSuchElementException, если в ДОМ.

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, вы должны заменить метод findElement () в ElementLocator чем-то вроде этого:

...
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
   }
}
5
Андрей Шкроб

Я недавно наткнулся на этот старый пост и считаю, что нашел одно решение. 

Я тестировал страницу с кнопкой Add User. При нажатии кнопки появлялись различные редактируемые текстовые поля (для имени, фамилии, адреса электронной почты и т.д.) И один раскрывающийся список. 

При нажатии кнопки Cancel поля исчезли и больше не существовали. Использование WebDriverWait с ExpectedConditions.visibilityOf() не будет работать, так как элементы больше не существуют в DOM

Я обнаружил, что @FindAll был для меня решением, хотя я должен признать, что мой тест выполнялся заметно медленнее при утверждении моего Списка.

Для вашего кода, что-то вроде этого:

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

1
T.D.

Я использую этот шаблон, отлично работает для меня:

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
prs

Использование привязок 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() в списке, который оценивается как true, если был найден хотя бы один IWebElement.

0
Pete

Arquillian реализовал эту функцию в Graphene extension.

Проверьте ElementLocatorConditionFactory.isPresent() function.

Они более или менее выполняют то, что вы написали в своем вопросе (из ExpectedConditions.findElement в Selenium-support.jar ):

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

@Ralph: я делаю то же самое: пробуй/лови. Я никогда не находил другого способа .. Вы можете поменять блок try/catch в суперклассе и спроектировать его generic. Другими словами: вы можете написать метод, который ожидает объект типа WebElement . Этот метод содержит блок try/catch и возвращает true/false ...

Поэтому я написал следующий публичный метод в test framework 's super class и теперь могу использовать его в каждом page объект :

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

Я не знаю, почему это не реализовано в WebDriver ...

В противном случае вы можете использовать WebDriverWait .

0
Flo Bayer