[java] Selenium WebDriver : JavaScript가있는 복잡한 페이지가로드 될 때까지 기다립니다.

Selenium으로 테스트 할 웹 애플리케이션이 있습니다. 페이지로드시 많은 JavaScript가 실행됩니다.
이 JavaScript 코드는 잘 작성되지 않았지만 아무것도 변경할 수 없습니다. 따라서 findElement()메서드 를 사용하여 요소가 DOM에 나타날 때까지 기다리는 것은 옵션이 아닙니다.
페이지가로드 될 때까지 기다리기 위해 Java에서 일반 함수를 만들고 싶습니다. 가능한 해결책은 다음과 같습니다.

  • WebDriver에서 JavaScript 스크립트를 실행하고 그 결과를 document.body.innerHTML문자열 변수에 저장합니다 body.
  • 비교] body의 이전 버전으로 변수를 body. 같으면 카운터 증가를 설정하고 notChangedCount그렇지 않으면 notChangedCount0으로 설정 합니다.
  • litte 시간을 기다립니다 (예 : 50ms).
  • 페이지가 일정 시간 동안 (예 : 500ms) 변경되지 notChangedCount >= 10않은 경우 루프를 종료하고 그렇지 않으면 첫 번째 단계로 루프합니다.

이것이 유효한 해결책이라고 생각하십니까?



답변

누군가가 일반적이고 항상 적용 가능한 대답을 실제로 알고 있다면 그것은 오래 전에 모든 곳 에서 구현되었을 것이며 우리의 삶을 훨씬 더 쉽게 만들 것입니다.

할 수있는 일이 많지만 모든 일에는 문제가 있습니다.

  1. 애쉬 윈 프라 부 말했듯이 당신이 잘 스크립트를 알고있는 경우에, 당신의 행동을 관찰하고에 그 변수의 일부를 추적 할 수 있습니다 window또는 document등이 솔루션을하지만, 모든 사람이 아니므로 오직 제한된에서만 사용할 수 있습니다 페이지.

  2. HTML 코드를 관찰하고 일정 기간 동안 변경되었는지 여부를 확인하는 솔루션은 나쁘지 않습니다 (또한 직접 편집하지 않은 원본 HTML을 가져 오는 방법도 있습니다 WebDriver).

    • 실제로 페이지를 주장하는 데 오랜 시간이 걸리며 테스트 시간이 크게 연장 될 수 있습니다.
    • 올바른 간격이 무엇인지 결코 알 수 없습니다. 스크립트 500ms 이상 걸리는 큰 파일을 다운로드 할 있습니다. IE에서 몇 초가 걸리는 회사의 내부 페이지에는 여러 스크립트가 있습니다. 컴퓨터의 리소스가 일시적으로 부족할 수 있습니다. 즉, 바이러스 백신이 CPU를 완전히 작동시킬 수 있다고 말하면 복잡하지 않은 스크립트의 경우에도 500ms가 너무 짧을 수 있습니다.
    • 일부 스크립트는 수행되지 않습니다. 그들은 약간의 지연 ( setTimeout())을 가지고 자신을 호출하고 반복해서 작동하며 실행될 때마다 HTML을 변경할 수 있습니다. 진지하게, 모든 “웹 2.0″페이지가 그렇게합니다. 심지어 스택 오버플로. 사용되는 가장 일반적인 방법을 덮어 쓰고이를 사용하는 스크립트를 완료된 것으로 간주 할 수 있지만 … 확실하지 않습니다.
    • 스크립트가 HTML 변경 이외의 작업을 수행하면 어떻게됩니까? innerHTML재미 뿐만 아니라 수천 가지 일을 할 수 있습니다.
  3. 이에 도움이되는 도구가 있습니다. 즉 , nsIWebProgressListener 및 다른 일부 와 함께 진행 리스너 입니다. 그러나 이에 대한 브라우저 지원은 끔찍합니다. Firefox는 FF4부터 지원하기 시작했으며 (아직 발전하고 있음) IE는 IE9에서 기본 지원을 제공합니다.

그리고 곧 또 다른 결함이있는 해결책을 찾을 수있을 것 같습니다. 사실은-작업을 수행하는 영원한 스크립트 때문에 “이제 페이지가 완성되었습니다”라고 말할시기에 대한 명확한 대답이 없습니다. 당신에게 가장 잘 봉사하는 것을 선택하되 단점을 조심하십시오.


답변

감사합니다 Ashwin!

제 경우에는 일부 요소에서 jquery 플러그인 실행을 기다려야합니다. 특히 “qtip”

귀하의 힌트를 바탕으로 완벽하게 작동했습니다.

wait.until( new Predicate<WebDriver>() {
            public boolean apply(WebDriver driver) {
                return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
            }
        }
    );

참고 : Webdriver 2를 사용하고 있습니다.


답변

Javascript 및 jQuery가로드를 완료 할 때까지 기다려야합니다. 자바 스크립트를 실행하여 jQuery.activeis 0document.readyStateis 인지 확인합니다 complete. 이는 JS 및 jQuery로드가 완료되었음을 의미합니다.

public boolean waitForJStoLoad() {

    WebDriverWait wait = new WebDriverWait(driver, 30);

    // wait for jQuery to load
    ExpectedCondition<Boolean> jQueryLoad = new ExpectedCondition<Boolean>() {
      @Override
      public Boolean apply(WebDriver driver) {
        try {
          return ((Long)executeJavaScript("return jQuery.active") == 0);
        }
        catch (Exception e) {
          return true;
        }
      }
    };

    // wait for Javascript to load
    ExpectedCondition<Boolean> jsLoad = new ExpectedCondition<Boolean>() {
      @Override
      public Boolean apply(WebDriver driver) {
        return executeJavaScript("return document.readyState")
            .toString().equals("complete");
      }
    };

  return wait.until(jQueryLoad) && wait.until(jsLoad);
}


답변

JS 라이브러리가 창에서 잘 알려진 변수를 정의 / 초기화합니까?

그렇다면 변수가 나타날 때까지 기다릴 수 있습니다. 당신이 사용할 수있는

((JavascriptExecutor)driver).executeScript(String script, Object... args)

이 조건 (예 :)을 테스트 window.SomeClass && window.SomeClass.variable != null하고 부울 true/을 반환합니다 false.

이것을로 감싸고 WebDriverWait스크립트가 반환 될 때까지 기다립니다 true.


답변

나는 같은 문제가 있었다. 이 솔루션은 WebDriverDoku에서 저에게 효과적입니다.

WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.id("someid")));

http://www.seleniumhq.org/docs/04_webdriver_advanced.jsp


답변

요소와 상호 작용을 시도하기 전에 페이지의 html이 안정 될 때까지 기다리기만하면 DOM을 주기적으로 폴링하고 결과를 비교할 수 있습니다. DOM이 주어진 폴링 시간 내에 동일하면 황금. 비교하기 전에 최대 대기 시간과 페이지 폴링 사이의 시간을 전달하는 것과 같은 것입니다. 간단하고 효과적입니다.

public void waitForJavascript(int maxWaitMillis, int pollDelimiter) {
    double startTime = System.currentTimeMillis();
    while (System.currentTimeMillis() < startTime + maxWaitMillis) {
        String prevState = webDriver.getPageSource();
        Thread.sleep(pollDelimiter); // <-- would need to wrap in a try catch
        if (prevState.equals(webDriver.getPageSource())) {
            return;
        }
    }
}


답변

아래 코드는 내 경우 완벽하게 작동합니다-내 페이지에는 복잡한 자바 스크립트가 포함되어 있습니다.

public void checkPageIsReady() {

  JavascriptExecutor js = (JavascriptExecutor)driver;


  //Initially bellow given if condition will check ready state of page.
  if (js.executeScript("return document.readyState").toString().equals("complete")){
   System.out.println("Page Is loaded.");
   return;
  }

  //This loop will rotate for 25 times to check If page Is ready after every 1 second.
  //You can replace your value with 25 If you wants to Increase or decrease wait time.
  for (int i=0; i<25; i++){
   try {
    Thread.sleep(1000);
    }catch (InterruptedException e) {}
   //To check page ready state.
   if (js.executeScript("return document.readyState").toString().equals("complete")){
    break;
   }
  }
 }

출처 -Selenium WebDriver에서 페이지가로드 / 준비되기를 기다리는 방법