programing tip

Selenium-WebDriver에 Java에서 몇 초 동안 기다리도록 어떻게 요청할 수 있습니까?

itbloger 2020. 8. 27. 07:26
반응형

Selenium-WebDriver에 Java에서 몇 초 동안 기다리도록 어떻게 요청할 수 있습니까?


Java Selenium-WebDriver에서 일하고 있습니다. 나는 추가했다

driver.manage().timeouts().implicitlyWait(2, TimeUnit.SECONDS);

WebElement textbox = driver.findElement(By.id("textbox"));

내 응용 프로그램이 사용자 인터페이스를로드하는 데 몇 초가 걸리기 때문입니다. 그래서 2 초를 implicitwait로 설정했습니다. 하지만 요소 텍스트 상자를 찾을 수 없습니다.

그런 다음 추가 Thread.sleep(2000);

이제 잘 작동합니다. 어느 것이 더 좋은 방법입니까?


음, 대기에는 명시 적 대기와 암시 적 대기라는 두 가지 유형이 있습니다. 명시 적 대기의 개념은

WebDriverWait.until(condition-that-finds-the-element);

암시 적 대기의 개념은

driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);

자세한 내용은 여기 에서 확인할 수 있습니다 .

이러한 상황에서는 명시 적 대기 ( fluentWait특히)를 사용하는 것을 선호합니다 .

public WebElement fluentWait(final By locator) {
    Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
            .withTimeout(30, TimeUnit.SECONDS)
            .pollingEvery(5, TimeUnit.SECONDS)
            .ignoring(NoSuchElementException.class);

    WebElement foo = wait.until(new Function<WebDriver, WebElement>() {
        public WebElement apply(WebDriver driver) {
            return driver.findElement(locator);
        }
    });

    return  foo;
};

fluentWait함수는 찾은 웹 요소를 반환합니다. 에 대한 설명서에서 fluentWait: 시간 초과 및 폴링 간격을 즉시 구성 할 수있는 Wait 인터페이스의 구현입니다. 각 FluentWait 인스턴스는 조건을 확인하는 빈도뿐 아니라 조건을 기다리는 최대 시간을 정의합니다. 또한 사용자는 페이지의 요소를 검색 할 때 NoSuchElementExceptions와 같이 대기하는 동안 특정 유형의 예외를 무시하도록 대기를 구성 할 수 있습니다. 여기에서 얻을 수있는 세부 정보

fluentWait귀하의 경우 사용은 다음과 같습니다.

WebElement textbox = fluentWait(By.id("textbox"));

이 접근법은 얼마나 많은 시간을 기다려야하는지 정확히 알지 못하기 때문에 IMHO가 더 좋습니다. 폴링 간격에서 요소 존재를 확인할 임의의 시간 값을 설정할 수 있습니다. 문안 인사.


webdriverJs (node.js)를 사용하는 경우

driver.findElement(webdriver.By.name('btnCalculate')).click().then(function() {
    driver.sleep(5000);
});

위의 코드는 브라우저가 버튼을 클릭 한 후 5 초 동안 기다리게합니다.


이 스레드는 조금 오래되었지만 현재 수행중인 작업 (진행중인 작업)을 게시 할 것이라고 생각했습니다.

여전히 시스템 부하가 true높고 제출 버튼 (예 : login.jsp)을 클릭하면 세 가지 조건 (아래 참조)이 모두 반환 되지만 다음 페이지 (예 : home.jsp)는 반환 되지 않습니다. t는 아직로드를 시작했습니다.

ExpectedConditions 목록을 사용하는 일반 대기 메서드입니다.

public boolean waitForPageLoad(int waitTimeInSec, ExpectedCondition<Boolean>... conditions) {
    boolean isLoaded = false;
    Wait<WebDriver> wait = new FluentWait<>(driver)
            .withTimeout(waitTimeInSec, TimeUnit.SECONDS)
            .ignoring(StaleElementReferenceException.class)
            .pollingEvery(2, TimeUnit.SECONDS);
    for (ExpectedCondition<Boolean> condition : conditions) {
        isLoaded = wait.until(condition);
        if (isLoaded == false) {
            //Stop checking on first condition returning false.
            break;
        }
    }
    return isLoaded;
}

재사용 가능한 다양한 ExpectedConditions를 정의했습니다 (아래에 3 개). 이 예에서 예상되는 세 가지 조건에는 document.readyState = 'complete', "wait_dialog"없음 및 'spinners'없음 (비동기 데이터가 요청됨을 나타내는 요소)가 포함됩니다.

일반적으로 모든 웹 페이지에 첫 번째 항목 만 적용 할 수 있습니다.

/**
 * Returns 'true' if the value of the 'window.document.readyState' via
 * JavaScript is 'complete'
 */
public static final ExpectedCondition<Boolean> EXPECT_DOC_READY_STATE = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        String script = "if (typeof window != 'undefined' && window.document) { return window.document.readyState; } else { return 'notready'; }";
        Boolean result;
        try {
            result = ((JavascriptExecutor) driver).executeScript(script).equals("complete");
        } catch (Exception ex) {
            result = Boolean.FALSE;
        }
        return result;
    }
};
/**
 * Returns 'true' if there is no 'wait_dialog' element present on the page.
 */
public static final ExpectedCondition<Boolean> EXPECT_NOT_WAITING = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        Boolean loaded = true;
        try {
            WebElement wait = driver.findElement(By.id("F"));
            if (wait.isDisplayed()) {
                loaded = false;
            }
        } catch (StaleElementReferenceException serex) {
            loaded = false;
        } catch (NoSuchElementException nseex) {
            loaded = true;
        } catch (Exception ex) {
            loaded = false;
            System.out.println("EXPECTED_NOT_WAITING: UNEXPECTED EXCEPTION: " + ex.getMessage());
        }
        return loaded;
    }
};
/**
 * Returns true if there are no elements with the 'spinner' class name.
 */
public static final ExpectedCondition<Boolean> EXPECT_NO_SPINNERS = new ExpectedCondition<Boolean>() {
    @Override
    public Boolean apply(WebDriver driver) {
        Boolean loaded = true;
        try {
        List<WebElement> spinners = driver.findElements(By.className("spinner"));
        for (WebElement spinner : spinners) {
            if (spinner.isDisplayed()) {
                loaded = false;
                break;
            }
        }
        }catch (Exception ex) {
            loaded = false;
        }
        return loaded;
    }
};

페이지에 따라 하나 또는 모두를 사용할 수 있습니다.

waitForPageLoad(timeoutInSec,
            EXPECT_DOC_READY_STATE,
            EXPECT_NOT_WAITING,
            EXPECT_NO_SPINNERS
    );

다음 클래스에도 사전 정의 된 ExpectedConditions가 있습니다. org.openqa.selenium.support.ui.ExpectedConditions


사용 Thread.sleep(2000);은 무조건 기다립니다. 테스트가 더 빨리로드 되더라도 기다려야합니다. 따라서 원칙적으로 사용 implicitlyWait하는 것이 더 나은 솔루션입니다.

그러나 implicitlyWait귀하의 경우에는 작동하지 않는지 알 수 없습니다. findElement예외가 발생하기 전에 실제로 2 초가 걸리는지 측정 했습니까? 그렇다면 답변에 설명 된대로 WebDriver의 조건부 대기를 사용해 볼 수 있습니까?


사용자 지정 조건을 사용하고 싶습니다. 다음은 Python의 일부 코드입니다.

def conditions(driver):
    flag = True
    ticker = driver.find_elements_by_id("textbox")
    if not ticker:
        flag = False
    return flag

... click something to load ...
self.wait = WebDriverWait(driver, timeout)
self.wait.until(conditions)

Whenever you need to wait, you can do it explicitly by checking existance of a certain element (such element may vary from page to page). find_elements_by_id returns list - empty or not, you have just to check.


click appears to be blocking? - here's another way to wait if you're using WebDriverJS:

driver.findElement(webdriver.By.name('mybutton')).click().then(function(){
  driver.getPageSource().then(function(source) {
    console.log(source);
  });
});

The code above waits after the button is clicked for the next page to load and then grabs the source of the next page.


Implicitly wait and Thread.sleep Both are used for synchronization only..but the difference is we can use Implicitly wait for entire program but Thread.sleep will works for that single code only..Here my suggestion is use Implicitly wait once in the program when every time your Webpage will get refreshed means use Thread.sleep at that time..it will much Better :)

Here is My Code :

package beckyOwnProjects;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;

public class Flip {

    public static void main(String[] args) throws InterruptedException {
        WebDriver driver=new FirefoxDriver();
        driver.manage().window().maximize();
        driver.manage().timeouts().implicitlyWait(2, TimeUnit.MINUTES);
        driver.get("https://www.flipkart.com");
    WebElement ele=driver.findElement(By.cssSelector(".menu-text.fk-inline-block"));
    Actions act=new Actions(driver);
    Thread.sleep(5000);
    act.moveToElement(ele).perform();
    }

}

Sometimes implicit wait seems to get overridden and wait time is cut short. [@eugene.polschikov] had good documentation on the whys. I have found in my testing and coding with Selenium 2 that implicit waits are good but occasionally you have to wait explicitly.

It is better to avoid directly calling for a thread to sleep, but sometimes there isn't a good way around it. However, there are other Selenium provided wait options that help. waitForPageToLoad and waitForFrameToLoad have proved especially useful.


Implicit Wait: During Implicit wait if the Web Driver cannot find it immediately because of its availability, the WebDriver will wait for mentioned time and it will not try to find the element again during the specified time period. Once the specified time is over, it will try to search the element once again the last time before throwing exception. The default setting is zero. Once we set a time, the Web Driver waits for the period of the WebDriver object instance.

Explicit Wait: There can be instance when a particular element takes more than a minute to load. In that case you definitely not like to set a huge time to Implicit wait, as if you do this your browser will going to wait for the same time for every element. To avoid that situation you can simply put a separate time on the required element only. By following this your browser implicit wait time would be short for every element and it would be large for specific element.


Sometimes implicit wait fails, saying that an element exists but it really doesn't.

The solution is to avoid using driver.findElement and to replace it with a custom method that uses an Explicit Wait implicitly. For example:

import org.openqa.selenium.NoSuchElementException;


public WebElement element(By locator){
    Integer timeoutLimitSeconds = 20;
    WebDriverWait wait = new WebDriverWait(driver, timeoutLimitSeconds);
    try {
        wait.until(ExpectedConditions.presenceOfElementLocated(locator));
    }
    catch(TimeoutException e){
        throw new NoSuchElementException(locator.toString());
    }
    WebElement element = driver.findElement(locator);
    return element;
}

There are additional reasons to avoid implicit wait other than sporadic, occasional failures (see this link).

You can use this "element" method in the same way as driver.findElement. For Example:

    driver.get("http://yoursite.html");
    element(By.cssSelector("h1.logo")).click();

If you really want to just wait a few seconds for troubleshooting or some other rare occasion, you can create a pause method similar to what selenium IDE offers:

    public void pause(Integer milliseconds){
    try {
        TimeUnit.MILLISECONDS.sleep(milliseconds);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

Answer : wait for few seconds before element visibility using Selenium WebDriver go through below methods.

implicitlyWait() : WebDriver instance wait until full page load. You muse use 30 to 60 seconds to wait full page load.

driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);

ExplicitlyWait WebDriverWait() : WebDriver instance wait until full page load.

WebDriverWait wait = new WebDriverWait(driver, 60);

wait.until(ExpectedConditions.visibilityOf(textbox));

driver.findElement(By.id("Year")).sendKeys(allKeys);

Note : Please use ExplicitlyWait WebDriverWait() to handle any particular WebElement.


I prefer the following code to wait for 2 seconds.

for(int i=0; i<2 && driver.findElements(By.id("textbox")).size()==0 ; i++){
   Thread.sleep(1000);
}

Thread.sleep(1000);

is the worse: being a static wait, it will make test script slower.

driver.manage().timeouts.implicitlyWait(10,TimeUnit.SECONDS);

this is a dynamic wait

  • it is valid till webdriver existence or has a scope till driver lifetime
  • we can implicit wait also.

Finally, what I suggest is

WebDriverWait wait = new WebDriverWait(driver,20);
wait.until(ExpectedConditions.<different canned or predefined conditions are there>);

with some predefined conditions:

isAlertPresent();
elementToBeSelected();
visibilityOfElementLocated();
visibilityOfAllElementLocatedBy();
frameToBeAvailableAndSwitchToIt();
  • It is also dynamic wait
  • in this the wait will only be in seconds
  • we have to use explicit wait for a particular web element on which we want to use.

Thread.Sleep(5000);

This did help me but InterruptedException exception needs to be taken care of. So better surround it with try and catch:

try {
    Thread.Sleep(5000);
} catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

OR

Add throws declaration:

public class myClass {
    public static void main(String[] args) throws InterruptedException
    { ... }

I would prefer the second one since one can then use sleep() as many times as it wants and avoid the repetition of try and catch block every time wherever sleep() has been used.

참고URL : https://stackoverflow.com/questions/12858972/how-can-i-ask-the-selenium-webdriver-to-wait-for-few-seconds-in-java

반응형