Проверить наличие элемента с помощью Selenium WebDriver?

163

Есть ли способ, как проверить наличие элемента? Любой метод findElement заканчивался бы исключением, но это не то, что я хочу, потому что может случиться так, что элемент отсутствует, и это нормально, это не провал теста, поэтому исключение не может быть решением.

Я нашел этот пост: Selenium c # Webdriver: Подождите, пока элемент не появится, но это для C #, и я не очень хорош в этом. Кто-нибудь может перевести код на Java? Прошу прощения, ребята, я попробовал это в Eclipse, но я не совсем понял это в Java-коде.

Это код:

public static class WebDriverExtensions{
    public static IWebElement FindElement(this IWebDriver driver, By by, int timeoutInSeconds){

        if (timeoutInSeconds > 0){
            var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(timeoutInSeconds));
            return wait.Until(drv => drv.FindElement(by));
        }

        return driver.FindElement(by);
    }
}
тестер
источник
У меня есть несколько методов, которые очень эффективно работают при проверке объекта, но это зависит от того, что вы хотите с ним сделать. Например, хотите ли вы искать элемент, пока он не существует, хотите ли вы искать его, пока он больше не существует, или вы просто хотите найти его?
CBRRacer
1
Java очень похожа на C # Я думаю, что одна из основных проблем, с которыми вы здесь сталкиваетесь, заключается в том, что в Java это WebElement вместо IWebElement
CBRRacer
Знаете ли вы о неявном методе ожидания? Установив это в начале теста, вам никогда не придется проверять существование элемента, так как он использует неявное значение ожидания для опроса, однако, если оно превысит это значение, оно выдаст исключение
Боб Эванс
Вот мой пост о WebDriverWait в Java: WebDriverWait
Если в любом случае все в порядке, это может быть проблематично для производительности теста, поскольку время ожидания, связанное с ожиданием элемента, которого вы не ожидаете, действительно складывается. Я использовал несколько хаков, чтобы обойти время ожидания, но пока не нашел действительно чистого решения для этого.
mrfreester

Ответы:

277

Используйте findElementsвместо findElement.

findElements вернет пустой список, если не найдены подходящие элементы вместо исключения.

Чтобы проверить наличие элемента, вы можете попробовать это

Boolean isPresent = driver.findElements(By.yourLocator).size() > 0

Это вернет true, если хотя бы один элемент найден, и false, если он не существует.

Официальная документация рекомендует этот метод:

findElement не должен использоваться для поиска несуществующих элементов, используйте findElements (By) и вместо этого утверждайте ответ нулевой длины.

Эль Росо
источник
32
Это добавит много времени для запуска ваших тестов. Вы не можете использовать эту технику везде.
Дрооганс
8
@Droogans - я не буду добавлять время на ваши тесты. Причина этого заключается в том, что неявное ожидание по умолчанию все еще равно 0. Если вы увеличили неявное ожидание по умолчанию, то я согласен, что это произойдет, но здесь это не так.
Джангофан
1
Хорошо позвони Джангофану! Я успешно использовал эту стратегию, изменив неявное ожидание тайм-аута драйвера до нуля, а затем вернув его к предыдущему значению.
Эмери
3
Это дало исключение NoSuchElementFound, и это позор, поскольку я надеялся использовать это, чтобы избежать перехвата этого исключения в данном экземпляре.
1
Гораздо более простой способ - использовать: if (driver.getPageSource (). Содержит («Текст на странице»)) {} Если страница содержит этот текст, то условие будет истинным, иначе оно будет ложным, и вы можете закодировать соответственно.
Прадёт
56

Как насчет частного метода, который просто ищет элемент и определяет, присутствует ли он следующим образом:

private boolean existsElement(String id) {
    try {
        driver.findElement(By.id(id));
    } catch (NoSuchElementException e) {
        return false;
    }
    return true;
}

Это было бы довольно легко и делает работу.

Изменить: вы могли бы даже пойти дальше и принять в By elementLocatorкачестве параметра, устраняя проблемы, если вы хотите найти элемент по чему-то, кроме идентификатора.

Деннис
источник
3
Да, это путь. Не понимаю, почему люди игнорируют этот способ и считают соответствующие элементы, чтобы увидеть, равен ли результат 0.
Ральф Лавель
45
Ну, я должен сказать, что использование исключений для регулирования потока программы - не лучший способ.
Деннис
2
А? Это было ваше предложение! Это хороший способ, если ваш тест ожидает, что элемент не будет найден. Как вы показываете, просто верните null и assert.isnull или isnotnull, что является значимым способом проверить, существует ли вещь.
Ральф Лавель
2
В случае, если я неправильно истолковал вопрос "есть ли способ проверить, присутствует ли элемент?" неправильно, я буду рад узнать, почему ваше мнение отличается от того, является ли это законным ответом.
Деннис
Возможно, вы захотите сократить время ожидания. Прямо сейчас, если элемент не существует, вы должны подождать «30 секунд», прежде чем функция вернет false
Джейсон Смайли
14

Я обнаружил, что это работает для Java:

WebDriverWait waiter = new WebDriverWait(driver, 5000);
waiter.until( ExpectedConditions.presenceOfElementLocated(by) );
driver.FindElement(by);
Танго бен
источник
18
presenceOfElementLocatedвыдаст исключение, если элемент не найден при какой-либо конкретной попытке. Чтобы избежать этого, добавьте wait.ignoring(NoSuchElementException.class);оператор между первой и второй строкой.
Стив Чемберс
8
public static WebElement FindElement(WebDriver driver, By by, int timeoutInSeconds)
{
    WebDriverWait wait = new WebDriverWait(driver, timeoutInSeconds);
    wait.until( ExpectedConditions.presenceOfElementLocated(by) ); //throws a timeout exception if element not present after waiting <timeoutInSeconds> seconds
    return driver.findElement(by);
}
RedDeckWins
источник
5

Я была такая же проблема. Для меня, в зависимости от уровня разрешений пользователя, некоторые ссылки, кнопки и другие элементы не будут отображаться на странице. Часть моего набора тестировала, что элементы, которые ДОЛЖНЫ отсутствовать, отсутствуют. Я часами пытался понять это. Я наконец нашел идеальное решение.

Что он делает, так это говорит браузеру искать все элементы на основе указанных. Если это приводит к тому 0, что это означает, что элементы, основанные на спецификации, не были найдены. Затем у меня есть код выполнения оператора if, чтобы сообщить, что он не был найден.

Это в C#, так что переводы должны быть сделаны для Java. Но не должно быть слишком сложно.

public void verifyPermission(string link)
{
    IList<IWebElement> adminPermissions = driver.FindElements(By.CssSelector(link));
    if (adminPermissions.Count == 0)
    {
        Console.WriteLine("User's permission properly hidden");
    }
}

Есть также другой путь, который вы можете выбрать в зависимости от того, что вам нужно для теста.

Следующий фрагмент проверяет, существует ли на странице очень специфический элемент. В зависимости от существования элемента я могу выполнить тест if else.

Если элемент существует и отображается на странице, я console.writeдал мне знать и двигаться дальше. Если рассматриваемый элемент существует, я не могу выполнить необходимый мне тест, что является основной причиной необходимости его настройки.

Если элемент не существует и не отображается на странице. У меня есть еще в если еще выполнить тест.

IList<IWebElement> deviceNotFound = driver.FindElements(By.CssSelector("CSS LINK GOES HERE"));
//if the element specified above results in more than 0 elements and is displayed on page execute the following, otherwise execute whats in the else statement
if (deviceNotFound.Count > 0 && deviceNotFound[0].Displayed){
    //script to execute if element is found
} else {
    //Test script goes here.
}

Я знаю, что немного опоздала с ответом на ФП. Надеюсь, это кому-нибудь поможет!

Tasha
источник
5

Попробуйте это: вызовите этот метод и передайте 3 аргумента:

  1. Переменная WebDriver. // предполагая, что driver_variable является драйвером.
  2. Элемент, который вы собираетесь проверить. Должен предоставлять из метода. // ex: By.id ("id")
  3. Ограничение по времени в секундах.

Пример: waitForElementPresent (driver, By.id ("id"), 10);

public static WebElement waitForElementPresent(WebDriver driver, final By by, int timeOutInSeconds) {

        WebElement element; 

        try{
            driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS); //nullify implicitlyWait() 

            WebDriverWait wait = new WebDriverWait(driver, timeOutInSeconds); 
            element = wait.until(ExpectedConditions.presenceOfElementLocated(by));

            driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); //reset implicitlyWait
            return element; //return the element
        } catch (Exception e) {
            e.printStackTrace();
        } 
        return null; 
    }
Прабу Анантакришнан
источник
3

Вы можете ускорить выполнение кода, сократив время ожидания селен перед оператором try catch.

Я использую следующий код, чтобы проверить, присутствует ли элемент.

protected boolean isElementPresent(By selector) {
    selenium.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
    logger.debug("Is element present"+selector);
    boolean returnVal = true;
    try{
        selenium.findElement(selector);
    } catch (NoSuchElementException e){
        returnVal = false;
    } finally {
        selenium.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
    }
    return returnVal;
}
EsotericNonsense
источник
Это то, что я использую в своем коде. Я оставляю тайм-аут Selenium по умолчанию, а затем использую его.
Николас ДиПьяцца
2
После написания этого ответа я узнал, что использование ExpectedConditions считается лучшей формой, но использование оператора try catch все еще полезно при попытке определить, отсутствует ли элемент.
EsotericNonsense
Я застрял на старой версии селена, потому что я должен проверить IE8. но я попробую это, когда смогу обновить
Николас ДиПиацца
Каждый раз, когда ваш метод устанавливает неявное время ожидания, но логически мы должны устанавливать неявное ожидание только один раз после инициализации объекта драйвера, и время ожидания устанавливается для сеанса драйвера.
Шехар Свами,
3

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

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

Вызвать метод с соответствующим параметром во время утверждения.

Рипон Аль Васим
источник
2

если вы используете rspec-Webdriver в ruby, вы можете использовать этот скрипт, предполагая, что элемент действительно не должен присутствовать, и это пройденный тест.

Во-первых, сначала напишите этот метод из вашего файла класса RB

class Test
 def element_present?
    begin
        browser.find_element(:name, "this_element_id".displayed?
        rescue Selenium::WebDriver::Error::NoSuchElementError
            puts "this element should not be present"
        end
 end

Затем, в вашем spec-файле, вызовите этот метод.

  before(:all) do    
    @Test= Test.new(@browser)
  end

 @Test.element_present?.should == nil

Если ваш элемент НЕ присутствует, ваша спецификация пройдет, но если элемент присутствует, он выдаст ошибку, тест не пройден.

grayshell
источник
2

Это работает для меня:

 if(!driver.findElements(By.xpath("//*[@id='submit']")).isEmpty()){
    //THEN CLICK ON THE SUBMIT BUTTON
}else{
    //DO SOMETHING ELSE AS SUBMIT BUTTON IS NOT THERE
}
Амстел Байтс
источник
та же проблема существует здесь: что, если элемент "// * [@ id = 'submit']" не существует? тогда будет
сгенерировано
1
public boolean isElementDisplayed() {
        return !driver.findElements(By.xpath("...")).isEmpty();
    }
Богдан Шульга
источник
1

Лично я всегда использую смесь приведенных выше ответов и создаю метод статической утилиты многократного использования, который использует size() > 0предложение:

public Class Utility {
   ...
   public static boolean isElementExist(WebDriver driver, By by) {
      return driver.findElements(by).size() > 0;
   ...
}

Это аккуратно, многоразово, ремонтопригодно ... все это хорошо ;-)

Чарли Селигман
источник
0

Чтобы найти конкретный элемент или нет, мы должны использовать метод findElements () вместо findElement ().

int i=driver.findElements(By.xpath(".......")).size();
if(i=0)
System.out.println("Element is not present");
else
System.out.println("Element is present");

это работает для меня .. предложите мне, если я ошибаюсь ..

Суббарао Гаддам
источник
0

Это должно сделать это:

try {
    driver.findElement(By.id(id));
} catch (NoSuchElementException e) {
    //do what you need here if you were expecting
    //the element wouldn't exist
}
Скотт Хельме
источник
0

Дать мой фрагмент кода. Таким образом, приведенный ниже метод проверяет , существует ли на странице случайная кнопка « Создать новое приложение » или нет. Обратите внимание, что я использовал период ожидания как 0 секунд.

public boolean isCreateNewApplicationButtonVisible(){
    WebDriverWait zeroWait = new WebDriverWait(driver, 0);
    ExpectedCondition<WebElement> c = ExpectedConditions.presenceOfElementLocated(By.xpath("//input[@value='Create New Application']"));
    try {
        zeroWait.until(c);
        logger.debug("Create New Application button is visible");
        return true;
    } catch (TimeoutException e) {
        logger.debug("Create New Application button is not visible");
        return false;
    }
}
Rambo7
источник
0

Я бы использовал что-то вроде (со Scala [код в старой «хорошей» Java 8 может быть похож на это)):

object SeleniumFacade {

  def getElement(bySelector: By, maybeParent: Option[WebElement] = None, withIndex: Int = 0)(implicit driver: RemoteWebDriver): Option[WebElement] = {
    val elements = maybeParent match {
      case Some(parent) => parent.findElements(bySelector).asScala
      case None => driver.findElements(bySelector).asScala
    }
    if (elements.nonEmpty) {
      Try { Some(elements(withIndex)) } getOrElse None
    } else None
  }
  ...
}

тогда

val maybeHeaderLink = SeleniumFacade getElement(By.xpath(".//a"), Some(someParentElement))
сес
источник
0

Простейший способ, который я нашел в Java:

List<WebElement> linkSearch=  driver.findElements(By.id("linkTag"));
int checkLink=linkSearch.size();
if(checkLink!=0){  //do something you want}
back2back
источник
0

Вы можете попробовать неявное ожидание:

WebDriver driver = new FirefoxDriver();
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
driver.Url = "http://somedomain/url_that_delays_loading";
IWebElement myDynamicElement = driver.FindElement(By.Id("someDynamicElement"));

Или Вы можете попробовать явное ожидание:

IWebDriver driver = new FirefoxDriver();
driver.Url = "http://somedomain/url_that_delays_loading";
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement myDynamicElement = wait.Until<IWebElement>((d) =>
    {
        return d.FindElement(By.Id("someDynamicElement"));
    });

Явный проверит, присутствует ли элемент перед каким-либо действием. Неявное ожидание может быть вызвано в любом месте кода. Например, после некоторых действий AJAX.

Больше вы можете найти на странице SeleniumHQ

streser
источник