[java] 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가 더 좋습니다. 폴링 간격에서 요소 존재를 확인할 임의의 시간 값을 설정할 수 있습니다. 문안 인사.


답변

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

여전히 시스템 부하가 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


답변

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

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

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


답변

사용 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)

기다려야 할 때마다 특정 요소의 존재 여부를 확인하여 명시 적으로 수행 할 수 있습니다 (이러한 요소는 페이지마다 다를 수 있음). find_elements_by_id목록을 반환합니다-비어 있는지 여부를 확인하기 만하면됩니다.


답변

클릭이 차단되는 것처럼 보입니까? -WebDriverJS를 사용하는 경우 기다리는 또 다른 방법이 있습니다.

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

위의 코드는 버튼을 클릭 한 후 다음 페이지가로드 될 때까지 기다린 후 다음 페이지의 소스를 가져옵니다.


답변

암시 적으로 대기 및 Thread.sleep 둘 다 동기화에만 사용됩니다. 그러나 차이점은 암시 적으로 전체 프로그램을 기다릴 수 있지만 Thread.sleep은 해당 단일 코드에서만 작동합니다. 여기에서 내 제안은 프로그램에서 암시 적으로 한 번 대기하는 것입니다. 웹 페이지가 새로 고쳐질 때마다 그 시간에 Thread.sleep을 사용하십시오. 훨씬 나아질 것입니다. 🙂

내 코드는 다음과 같습니다.

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

}