Перевірте наявність елемента за допомогою 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

Це поверне справжнє значення, якщо знайдеться хоча б один елемент, а помилковий, якщо його не існує.

Офіційна документація рекомендує цей метод:

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


32
Це додасть багато часу, необхідного для запуску тестів. Ви не можете використовувати цю техніку скрізь.
Droogans

8
@Droogans - я не додаватиму час вашим тестам. Причиною цього є те, що неявне очікування за замовчуванням все ще дорівнює 0. Якщо ви збільшили неявне очікування за замовчуванням, то я погоджуюся, що це було б, але, здається, це не так.
djangofan

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параметр, усуваючи проблеми, якщо хочете знайти елемент за чимось іншим, ніж id.


3
Так, це шлях. Не розумію, чому люди ігнорують цей спосіб, і підраховують відповідні елементи, бачачи, чи результат 0.
Ральф Лавель

45
Ну, я мушу сказати, що використання винятків для регулювання потоку програми - це не найкращий шлях.
Денніс

2
Так? Це було вашою пропозицією! Це хороший шлях, якщо ваш тест розраховує не знайти елемент. Як ви показуєте, просто поверніть null і assert.isnull або isnotnull, що є значущим способом перевірити, чи є річ.
Ральф Лавель

2
У випадку, якщо я неправильно трактував питання, "чи є спосіб перевірити наявність елемента?" неправильно, я буду радий дізнатися, чому ваша думка відрізняється тим, чи є це законною відповіддю чи ні.
Денніс

можливо, потрібно скоротити час очікування. Зараз, якщо цього елемента немає, потрібно почекати "30 секунд", перш ніж функція повернеться помилково
Jason Smiley

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

Існує також інший шлях, який ви можете пройти в залежності від того, що вам потрібно для вашого тесту.

Наступний фрагмент перевіряє, чи існує на сторінці певний елемент. Залежно від існування елемента, я маю тест виконати якщо інше.

Якщо елемент існує і відображається на сторінці, я 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. // припускаючи, що драйвер_перемінний є драйвером.
  2. Елемент, який ви збираєтеся перевірити. Слід надати за методом. // ex: By.id ("id")
  3. Межа часу в секундах.

Приклад: waitForElementPresent (драйвер, 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

Ви можете змусити код запустити швидше, скоротивши тайм-аут селену перед тим, як спробувати заявку на випробування.

Я використовую наступний код, щоб перевірити наявність елемента.

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 в рубіні, ви можете використовувати цей скрипт, припускаючи, що елемент дійсно не повинен бути присутнім, і це пройдений тест.

Спочатку напишіть цей метод спочатку з файлу 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

Потім виберіть у своєму специфікаційному файлі цей метод.

  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']" не існує? тоді буде викинуто виняток, таким чином, якщо умовне ніколи не буде оцінено
MrBCut


1

Особисто я завжди шукаю суміш вищезазначених відповідей і створюю багаторазовий статичний метод Utility, який використовує 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.