Проверить наличие элемента с помощью 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);
}

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.
}

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


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;
}

Это то, что я использую в своем коде. Я оставляю тайм-аут 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

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


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

Лично я всегда использую смесь приведенных выше ответов и создаю метод статической утилиты многократного использования, который использует 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;
    }
}

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}

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.