Programing

WebDriver : 요소가 존재하는지 확인 하시겠습니까?

lottogame 2020. 7. 18. 10:26
반응형

WebDriver : 요소가 존재하는지 확인 하시겠습니까? [복제]


이 질문에는 이미 답변이 있습니다.

웹 드라이버에 요소가 있는지 확인하는 방법?

try catch를 사용하는 것이 실제로 가능한 유일한 방법입니까?

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

또는 다음을 수행 할 수 있습니다.

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

불쾌한 시도 / 캐치를 저장합니다.


Mike의 답변에 동의하지만 켜거나 끌 수있는 요소가 없으면 암시 적 3 초 대기가 있습니다.이 동작을 많이 수행하는 경우 유용합니다.

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

많은 테스트를 수행하는 경우 유틸리티 메소드에 넣으면 성능이 향상됩니다.


의견에서 언급했듯이 이것은 C #에 있지만 Java는 아니지만 아이디어는 동일합니다. 이 문제를 광범위하게 연구했으며 궁극적으로 문제는 요소가 존재하지 않을 때 FindElement가 항상 예외를 반환한다는 것입니다. 널이나 다른 것을 얻을 수있는 과부하 된 옵션이 없습니다. 다음은 다른 솔루션보다이 솔루션을 선호하는 이유입니다.

  1. 요소 목록을 반환 한 다음 목록 크기가 0인지 확인하지만 그렇게하면 기능이 손실됩니다. 컬렉션 크기가 1 인 경우에도 링크 컬렉션에서 .click ()을 수행 할 수 없습니다.
  2. 요소가 존재하지만 종종 테스트를 중지한다고 주장 할 수 있습니다. 경우에 따라 해당 페이지로 이동 한 방법에 따라 클릭 할 수있는 추가 링크가 있으며 페이지가있는 경우 클릭하거나 다른 방법으로 이동하고 싶습니다.
  3. 시간 초과 드라이버를 설정하지 않으면 속도가 느려집니다 .Manage (). Timeouts (). ImplicitlyWait (TimeSpan.FromSeconds (0));
  4. 메소드가 작성되면 실제로 매우 간단하고 우아합니다. 사용하여 FindElementSafe 대신 FindElement을 , 나는 추한 try / catch 블록을 "인식"하지 않습니다와 나는 간단한 사용할 수있는 존재 방법. 다음과 같이 보일 것입니다.

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

다형성을 사용하여 FindElement의 IWebDriver 클래스 인스턴스를 수정할 수 있지만 유지 관리 관점에서는 나쁜 생각입니다.


이것은 매번 나를 위해 작동합니다.

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

당신은 주장을 할 수 있습니다.

예를 참조하십시오

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

I extended Selenium WebDriver implementation, in my case HtmlUnitDriver to expose a method

public boolean isElementPresent(By by){}

like this:

  1. check if page is loaded within a timeout period.
  2. Once page is loaded, I lower the implicitly wait time of the WebDriver to some milliseconds, in my case 100 mills, probably should work with 0 mills too.
  3. call findElements(By), the WebDriver even if will not find the element will wait only the amount of time from above.
  4. rise back the implicitly wait time for future page loading

Here is my code:

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

Usage:

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

Write the following method using Java:

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

Call the above method during assertion.


String link = driver.findElement(By.linkText(linkText)).getAttribute("href")

This will give you the link the element is pointing to.


With version 2.21.0 of selenium-java.jar you can do this;

driver.findElement(By.id("...")).isDisplayed()

As I understand it, this is the default way of using the web driver.

참고URL : https://stackoverflow.com/questions/6521270/webdriver-check-if-an-element-exists

반응형