it-swarm.com.ru

WebDriver: проверить, существует ли элемент?

Как проверить, существует ли элемент с веб-драйвером?

Является ли использование try catch действительно единственным возможным способом?

boolean present;
try {
   driver.findElement(By.id("logoutLink"));
   present = true;
} catch (NoSuchElementException e) {
   present = false;
}
112
Ralph

Вы могли бы альтернативно сделать:

driver.findElements( By.id("...") ).size() != 0

Который спасает неприятную попытку/поймать

209
Mike Kwan

Я согласен с ответом Майка, но есть неявное 3-секундное ожидание, если не найдено элементов, которые можно включить/выключить, что полезно, если вы часто выполняете это действие:

driver.manage().timeouts().implicitlyWait(0, TimeUnit.MILLISECONDS);
boolean exists = driver.findElements( By.id("...") ).size() != 0
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);

Использование этого в служебном методе должно улучшить производительность, если вы выполняете много тестов

48
Edd

Как отмечается в комментарии, это в C # не Java, но идея та же. Я тщательно исследовал эту проблему, и в конечном итоге проблема заключается в том, что FindElement всегда возвращает исключение, когда элемент не существует. Нет перегруженной опции, которая позволяет вам получить значение null или что-то еще. Вот почему я предпочитаю это решение другим.

  1. Возврат списка элементов и проверка, равен ли размер списка 0, работает, но при этом вы теряете функциональность. Вы не можете сделать .click () для коллекции ссылок, даже если размер коллекции равен 1.
  2. Вы можете утверждать, что элемент существует, но часто это останавливает ваше тестирование. В некоторых случаях у меня есть дополнительная ссылка, чтобы щелкнуть в зависимости от того, как я попал на эту страницу, и я хочу щелкнуть по ней, если она существует, или перейти к другому.
  3. Это только медленно, если вы не установите время ожидания driver.Manage (). Timeouts (). ImplicitlyWait (TimeSpan.FromSeconds (0));
  4. Это на самом деле очень просто и элегантно, когда метод создан. Используя FindElementSafe вместо FindElement, я не "вижу" уродливый блок try/catch и могу использовать простой метод Exists. Это будет выглядеть примерно так:

    IWebElement myLink = driver.FindElementSafe(By.Id("myId"));
    if (myLink.Exists)
    {
       myLink.Click();
    }
    

Вот как вы расширяете IWebElement и IWebDriver

IWebDriver.FindElementSafe

    /// <summary>
    /// Same as FindElement only returns null when not found instead of an exception.
    /// </summary>
    /// <param name="driver">current browser instance</param>
    /// <param name="by">The search string for finding element</param>
    /// <returns>Returns element or null if not found</returns>
    public static IWebElement FindElementSafe(this IWebDriver driver, By by)
    {
        try
        {
            return driver.FindElement(by);
        }
        catch (NoSuchElementException)
        {
            return null;
        }
    }

IWebElement.Exists

    /// <summary>
    /// Requires finding element by FindElementSafe(By).
    /// Returns T/F depending on if element is defined or null.
    /// </summary>
    /// <param name="element">Current element</param>
    /// <returns>Returns T/F depending on if element is defined or null.</returns>
    public static bool Exists(this IWebElement element)
    {
        if (element == null)
        { return false; }
        return true;
    }

Вы можете использовать полиморфизм для изменения экземпляра класса IWebDriver FindElement, но это плохая идея с точки зрения обслуживания.

8
Brantley Blanchard

Это работает для меня каждый раз:

    if(!driver.findElements(By.xpath("//*[@id='submit']")).isEmpty()){
        //THEN CLICK ON THE SUBMIT BUTTON
    }else{
        //DO SOMETHING ELSE AS SUBMIT BUTTON IS NOT THERE
    }
4
Amstel Bytes

вы можете сделать утверждение.

посмотрите пример

driver.asserts().assertElementFound("Page was not loaded",
By.xpath("//div[@id='actionsContainer']"),Constants.LOOKUP_TIMEOUT);

вы можете использовать это, это родной:

public static void waitForElementToAppear(Driver driver, By selector, long timeOutInSeconds, String timeOutMessage) {
    try {
      WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds);
      wait.until(ExpectedConditions.visibilityOfElementLocated(selector));
    } catch (TimeoutException e) {
      throw new IllegalStateException(timeOutMessage);
    }
  }
3
Ran Adler

Я расширил реализацию Selenium WebDriver, в моем случае HtmlUnitDriver для предоставления метода

public boolean isElementPresent(By by){}

как это:

  1. проверьте, загружена ли страница в течение периода ожидания.
  2. После загрузки страницы я неявно ожидаю время ожидания WebDriver до нескольких миллисекунд, в моем случае 100 мельниц, вероятно, должно работать и с 0 мельницами.
  3. вызов findElements (By), WebDriver, даже если не найдет элемент, будет ждать только количество времени сверху.
  4. возвратите время ожидания загрузки страницы в будущем.

Вот мой код:

import Java.util.concurrent.TimeUnit;
import org.openqa.Selenium.By;
import org.openqa.Selenium.JavascriptExecutor;
import org.openqa.Selenium.WebDriver;
import org.openqa.Selenium.htmlunit.HtmlUnitDriver;
import org.openqa.Selenium.support.ui.ExpectedCondition;
import org.openqa.Selenium.support.ui.WebDriverWait;

public class CustomHtmlUnitDriver extends HtmlUnitDriver {

    public static final long DEFAULT_TIMEOUT_SECONDS = 30;
    private long timeout = DEFAULT_TIMEOUT_SECONDS;

    public long getTimeout() {
        return timeout;
    }
    public void setTimeout(long timeout) {
        this.timeout = timeout;
    }

    public boolean isElementPresent(By by) {
        boolean isPresent = true;
        waitForLoad();
        //search for elements and check if list is empty
        if (this.findElements(by).isEmpty()) {
            isPresent = false;
        }
        //rise back implicitly wait time
        this.manage().timeouts().implicitlyWait(timeout, TimeUnit.SECONDS);
        return isPresent;
    }

    public void waitForLoad() {
        ExpectedCondition<Boolean> pageLoadCondition = new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver wd) {
                //this will tel if page is loaded
                return "complete".equals(((JavascriptExecutor) wd).executeScript("return document.readyState"));
            }
        };
        WebDriverWait wait = new WebDriverWait(this, timeout);
        //wait for page complete
        wait.until(pageLoadCondition);
        //lower implicitly wait time
        this.manage().timeouts().implicitlyWait(100, TimeUnit.MILLISECONDS);
    }   
}

Использование:

CustomHtmlUnitDriver wd = new CustomHtmlUnitDriver();
wd.get("http://example.org");
if (wd.isElementPresent(By.id("Accept"))) {
    wd.findElement(By.id("Accept")).click();
}
else {
    System.out.println("Accept button not found on page");
}
2
Lotzy

Напишите следующий метод с использованием Java:

protected boolean isElementPresent(By by){
        try{
            driver.findElement(by);
            return true;
        }
        catch(NoSuchElementException e){
            return false;
        }
    }

Вызовите вышеуказанный метод во время утверждения.

1
Ripon Al Wasim
String link = driver.findElement(By.linkText(linkText)).getAttribute("href")

Это даст вам ссылку, на которую указывает элемент.

1
user1549161