Selenium WebDriver kullanarak öğenin mevcut olup olmadığını test ettiniz mi?


163

Bir elemanın mevcut olup olmadığını test etmenin bir yolu var mı? Herhangi bir findElement yöntemi bir istisna ile sona erecekti, ama istediğim bu değil, çünkü bir eleman mevcut olmayabilir ve tamam, bu testin bir başarısızlığı değil, bu yüzden bir istisna çözüm olamaz.

Bu gönderiyi buldum: Selenium c # Webdriver: Eleman Gelene Kadar Bekle Ama bu C # için ve çok iyi değilim. Herkes kodu Java'ya çevirebilir mi? Üzgünüm çocuklar, Eclipse'de denedim ama Java koduna giremiyorum.

Bu kod:

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

Bir nesneyi kontrol etmede çok etkili bir şekilde çalışan birkaç yöntemim var, ancak onunla ne yapmak istediğinize bağlı. örneğin öğeyi var olana kadar aramak istiyor musunuz, artık var olana kadar mı aramak istiyorsunuz yoksa sadece onu bulmak mı istiyorsunuz?
CBRRacer

1
Java, C # 'a çok benziyor Bence burada karşılaştığınız ana problemlerden biri, Java'da IWebElement yerine WebElement
CBRRacer

Örtülü bekleme yöntemi hakkında bilginiz var mı? Bunu testin başlangıcında kurarak, bir öğenin varlığını kontrol etmek zorunda kalmazsınız, çünkü yoklamak için örtülü bekleme değerini kullanır, ancak bu değeri aşarsa bir istisna atar
Bob Evans

İşte Java'da WebDriverWait hakkındaki

Her iki durumda da sorun yoksa, test performansı için sorunlu olabilir, çünkü var olmasını beklemediğiniz bir öğenin beklenmesi ile ilgili bekleme süresi gerçekten artıyor. Bekleme süresini aşmak için birkaç hack kullandım, ama bunun için gerçekten temiz bir çözüm bulamadım.
mrfreester

Yanıtlar:


277

Yerine findElementskullanın findElement.

findElements bir istisna yerine eşleşen öğe bulunamazsa boş bir liste döndürür.

Bir öğenin mevcut olup olmadığını kontrol etmek için şunu deneyebilirsiniz

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

Bu, en az bir öğe bulunduğunda true değerini ve yoksa false değerini döndürür.

Resmi belgeler bu yöntemi önerir:

findElement, mevcut olmayan öğeleri aramak için kullanılmamalı, findElements (By) işlevini kullanmalı ve bunun yerine sıfır uzunluklu yanıt talep etmelidir.


32
Bu, testlerinizi yürütmek için çok zaman harcayacaktır. Bu tekniği her yerde kullanamazsınız.
Droogans

8
@Droogans - Testlerinize zaman eklemeyeceğim. Bunun nedeni, varsayılan örtülü beklemenin hala 0 olması.
djangofan

1
İyi çağrı djangofan! Bu stratejiyi, sürücü zaman aşımlarının örtülü beklemesini sıfıra, ardından önceki değerine değiştirerek başarılı bir şekilde kullandım.
emery

3
Bu, belirli bir örnekte bu istisnayı yakalamaktan kaçınmayı umduğum için utanç verici bir NoSuchElementFound istisnası verdi.

1
Kullanmanın çok daha kolay yolu: if (driver.getPageSource (). İçerir ("Sayfadaki bir metin")) {} Sayfa bu metni içeriyorsa koşul doğru olur, aksi takdirde yanlış olur ve kodlayabilirsiniz buna göre.
pradyot

56

Sadece öğeyi arayan ve bunun mevcut olup olmadığını belirleyen özel bir yönteme ne dersiniz:

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

Bu oldukça kolay olurdu ve işi yapıyor.

Düzenleme: daha ileri gidebilir ve bir By elementLocatoras parametresi alabilir , öğeyi id dışında bir şeyle bulmak isterseniz sorunları ortadan kaldırabilirsiniz.


3
Evet, bu yol. İnsanların neden bu şekilde görmezden geldiğini ve eşleşen öğeleri
saydığını

45
Program akışını düzenlemek için Özel Durumlar'ı kullanmanın en iyi yol olmadığını söylemeliyim.
Dennis

2
Ha? Bu senin önerindi! Testiniz öğeyi bulmamayı beklerse iyi bir yoldur. Gösterdiğiniz gibi, null ve assert.isnull veya isnotnull öğelerini döndürün; bu, bir şeyin var olup olmadığını test etmenin anlamlı bir yoludur.
Ralph Lavelle

2
"Bir elemanın var olup olmadığını test etmenin bir yolu var mı?" yanlış, bunun meşru bir cevap olup olmadığı konusunda fikrinizin neden farklı olduğunu öğrenmekten memnuniyet duyarız.
Dennis

bekleme süresini azaltmak isteyebilir. Şu anda, öğe mevcut değilse, işlev yanlış dönmeden önce "30 saniye" beklemeniz gerekir
Jason Smiley

14

Bunun Java için çalıştığını gördüm:

WebDriverWait waiter = new WebDriverWait(driver, 5000);
waiter.until( ExpectedConditions.presenceOfElementLocated(by) );
driver.FindElement(by);

18
presenceOfElementLocatedöğe belirli bir denemede bulunamazsa bir İstisna atar. Bundan kaçınmak için wait.ignoring(NoSuchElementException.class);, birinci ve ikinci satır arasına bir ifade ekleyin .
Steve Chambers

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

Aynı sorunu yaşadım. Benim için, bir kullanıcının izin düzeyine bağlı olarak, bazı bağlantılar, düğmeler ve diğer öğeler sayfada gösterilmez. Paketimin bir kısmı, eksik olması gereken öğelerin eksik olduğunu test ediyordu. Bunu anlamaya çalışmak için saatler harcadım. Sonunda mükemmel çözümü buldum.

Bunun yaptığı, tarayıcıya belirtilen tüm elemanları aramasını söyler. Eğer sonuçlanırsa 0, bu spesifikasyona dayalı hiçbir eleman bulunmadığı anlamına gelir. Sonra kodu bulunamadı bana haber vermek için bir if deyimi yürütmek var.

Bu içeride C#, bu yüzden çevirilerin yapılması gerekiyor Java. Ama çok zor olmamalı.

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

Testiniz için neye ihtiyacınız olduğuna bağlı olarak atabileceğiniz başka bir yol daha var.

Aşağıdaki snippet, sayfada çok özel bir öğenin olup olmadığını kontrol ediyor. Elemanın varlığına bağlı olarak testin bir if ifrlemesini yürütmesini istiyorum.

Öğe varsa ve sayfada görüntülenirse, console.writebana bildirip devam ettim . Söz konusu öğe mevcutsa, ihtiyacım olan testi uygulayamıyorum, bu da bunu ayarlamanın arkasında yatan temel sebep.

Öğe Yoksa ve sayfada görüntülenmiyorsa. Başka bir test yürütmek if var.

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

OP'ye cevapta biraz geç kaldığımı biliyorum. Umarım bu birine yardımcı olur!


5

Bunu deneyin: Bu yöntemi çağırın ve 3 argüman iletin:

  1. WebDriver değişkeni. // driver_variable'ın driver olarak kabul edilmesi.
  2. Kontrol edeceğiniz öğe. By yönteminden sağlanmalıdır. // ör .: By.id ("kimlik")
  3. Saniye cinsinden zaman sınırı.

Örnek: waitForElementPresent (sürücü, 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 deyiminizden önce selenyum zaman aşımını kısaltarak kodun daha hızlı çalışmasını sağlayabilirsiniz.

Bir öğenin olup olmadığını kontrol etmek için aşağıdaki kodu kullanın.

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

Kodumda kullandığım bu. Selenium zaman aşımını varsayılan olarak bırakıyorum ve bunu kullanıyorum.
Nicholas DiPiazza

2
Bu yanıtı yazdığından beri ExpectedConditions kullanmanın daha iyi bir form olarak kabul edildiğini, ancak bir try catch deyiminin kullanılmasının, bir öğenin mevcut olup olmadığını belirlemeye çalışırken hala yararlı olduğunu öğrendim.
EsotericNonsense

IE8 test etmek zorunda olduğum için selenyum eski bir sürümü üzerinde sıkışıp kaldım. ama bunu yükseltebileceğim zaman deneyeceğim
Nicholas DiPiazza

Yönteminiz her zaman örtülü bekleme zaman aşımı ayarlayacaktır, ancak mantıksal olarak, sürücü nesnesini başlattıktan ve sürücü oturumuna zaman aşımı ayarlandıktan sonra örtülü bekleme ayarını yalnızca bir kez ayarlamalıyız.
Shekhar Swami

3

Java kullanarak aşağıdaki işlevi / yöntemleri yazın:

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

Doğrulama sırasında yöntemi uygun parametre ile çağırın.


2

ruby'de rspec-Webdriver kullanıyorsanız, bu komut dosyasını bir öğenin gerçekten olmaması gerektiğini ve başarılı bir test olduğunu varsayarak kullanabilirsiniz.

İlk olarak, bu yöntemi ilk önce sınıf RB dosyanızdan yazın

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

Ardından, spec dosyanızda bu yöntemi çağırın.

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

 @Test.element_present?.should == nil

Öğeniz yoksa, spesifikasyonunuz geçer, ancak öğe mevcutsa bir hata atar, test başarısız oldu.


2

Bu benim için çalışıyor:

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

burada da aynı sorun var: "// * [@ id = 'gönder']" öğesi yoksa? bir istisna atılır, böylece koşullu hiçbir zaman değerlendirilmezse
MrBCut

1
public boolean isElementDisplayed() {
        return !driver.findElements(By.xpath("...")).isEmpty();
    }

1

Şahsen, her zaman yukarıdaki cevapların bir karışımına gidiyorum ve size() > 0öneriyi kullanan yeniden kullanılabilir bir statik Utility yöntemi oluşturuyorum :

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

Bu temiz, yeniden kullanılabilir, bakımı kolay ... tüm bu iyi şeyler ;-)


0

Belirli bir Öğenin var olup olmadığını bulmak için findElement () yerine findElements () yöntemini kullanmamız gerekir.

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

bu benim için çalıştı .. yanılıyorsam bana öner ..


0

Bunu yapmalı:

try {
    driver.findElement(By.id(id));
} catch (NoSuchElementException e) {
    //do what you need here if you were expecting
    //the element wouldn't exist
}

0

Kod pasajımı veriyorum. Bu nedenle, aşağıdaki yöntem bir sayfada rastgele bir ' Yeni Uygulama Oluştur ' düğmesinin olup olmadığını kontrol eder. Bekleme süresini 0 saniye olarak kullandığımı unutmayın .

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 [eski "iyi" Java 8 koduna benzer olabilir) ile bir şey kullanırsınız:

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

e sonra,

val maybeHeaderLink = SeleniumFacade getElement(By.xpath(".//a"), Some(someParentElement))

0

Java'da bulduğum en basit yol:

List<WebElement> linkSearch=  driver.findElements(By.id("linkTag"));
int checkLink=linkSearch.size();
if(checkLink!=0){  //do something you want}

0

Örtülü beklemeyi deneyebilirsiniz:

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

Veya açık bir şekilde beklemeyi deneyebilirsiniz:

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

Açık, öğenin bir eylemden önce var olup olmadığını kontrol eder. Örtülü bekleme, kodun her yerine çağrılabilir. Örneğin bazı AJAX işlemlerinden sonra.

SeleniumHQ sayfasında daha fazlasını bulabilirsiniz

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.