2014-04-14 2 views
7

Java/Selenium을 사용하여 JavaScript API를 테스트하고 있습니다.Selenium은 JavaScript가 완료 될 때까지 기다릴 수 있습니까?

나는

자바 스크립트 측에서
executor.executeScript("setName('Hello');"); 
// Thread.sleep(2000); 
String output = (String)executor.executeScript("return getName()"); 
assertEquals(output, "Hello"); 

,이 비동기 함수, 자바 측에서이 명령을 실행, 그래서 그것은 시간이 좀 걸릴과 변수를 설정하기로되어있다.

function setName(msg) { 
    // simulate async call 
    setName(function(){name = msg;},1000); 
} 

나는이 비동기 기능은 assertEquals() 실행 자바에 다음 행으로 이동하기 전에 완료 될 때까지 기다릴 필요가있다.

Java 측에서 Thread.sleep()을 사용하지 않고이를 수행 할 수있는 방법이 있습니까?

감사합니다.

답변

2

특정 조건이 충족 될 때까지 Selenium에 대기하도록 쉽게 요청할 수 있습니다. 정확히 무슨에서, 하나 개의 대안은 다음과 같습니다

그러나
new FluentWait<JavascriptExecutor>(executor) { 
    protected RuntimeException timeoutException(
     String message, Throwable lastException) { 
    Assert.fail("name was never set"); 
    } 
}.withTimeout(10, SECONDS) 
.until(new Predicate<JavascriptExecutor>() { 
    public boolean apply(JavascriptExecutor e) { 
    return (Boolean)executor.executeScript("return ('Hello' === getName());"); 
    } 
}); 

는, 당신은 기본적으로 그냥 코딩 정확히 무엇을 테스트하고, 그리고 당신이 setName를 호출하기 전에 name이 설정된 경우 그 단점이있다, 당신 피난처에게 ' t는 반드시 setName을 끝내기를 기다렸다. 내 테스트 라이브러리에서

, 나는이 있습니다 (실제 비동기를 대체 setTimeout 심으로 호출) : 나는 비슷한 것들에 대한 과거에했던 것은 이것이다의 나머지 부분에서

window._junit_testid_ = '*none*'; 
window._junit_async_calls_ = {}; 
function _setJunitTestid_(testId) { 
    window._junit_testid_ = testId; 
} 
function _setTimeout_(cont, timeout) { 
    var callId = Math.random().toString(36).substr(2); 
    var testId = window._junit_testid_; 
    window._junit_async_calls_[testId] |= {}; 
    window._junit_async_calls_[testId][callId] = 1; 
    window.setTimeout(function(){ 
    cont(); 
    delete(window._junit_async_calls_[testId][callId]); 
    }, timeout); 
} 
function _isTestDone_(testId) { 
    if (window._junit_async_calls_[testId]) { 
    var thing = window._junit_async_calls_[testId]; 
    for (var prop in thing) { 
     if (thing.hasOwnProperty(prop)) return false; 
    } 
    delete(window._junit_async_calls_[testId]); 
    } 
    return true; 
} 

을 내 라이브러리에서 나중에 발생하도록 설정할 필요가있을 때마다 window.setTimeout 대신 _setTimeout_을 사용합니다. 필요한 경우이 waitForTest 여러 번 호출 할 수 있습니다

// First, this routine is in a library somewhere 
public void waitForTest(JavascriptExecutor executor, String testId) { 
    new FluentWait<JavascriptExecutor>(executor) { 
    protected RuntimeException timeoutException(
     String message, Throwable lastException) { 
     Assert.fail(testId + " did not finish async calls"); 
    } 
    }.withTimeout(10, SECONDS) 
    .until(new Predicate<JavascriptExecutor>() { 
    public boolean apply(JavascriptExecutor e) { 
     return (Boolean)executor.executeScript(
      "_isTestDone_('" + testId + "');"); 
    } 
    }); 
} 

// Inside an actual test: 
@Test public void serverPingTest() { 
    // Do stuff to grab my WebDriver instance 
    // Do this before any interaction with the app 
    driver.executeScript("_setJunitTestid_('MainAppTest.serverPingTest');"); 
    // Do other stuff including things that fire off what would be async calls 
    // but now call stuff in my testing library instead. 
    // ... 
    // Now I need to wait for all the async stuff to finish: 
    waitForTest(driver, "MainAppTest.serverPingTest"); 
    // Now query stuff about the app, assert things if needed 
} 

참고, 모든 비동기 작업이 완료 될 때까지 일시 중지 할 것을 테스트를 필요로하는 어떤 시간 : 그럼, 내 셀레늄 시험에서,이 같은 뭔가.

0

셀레늄이 의심 스럽습니다. 페이지가 완전히로드 될 때까지 대기하지만 스크립트는 완료되지 않습니다. 결과를 기다리는 (그리고 페이지 내용/스크립트 상태를 지속적으로 폴링하는) 자신 만의 '테스트 단계'를 정의 할 수도 있지만 테스트 오류가 발생하면 남성에게 테스트 시간이 멈추지 않도록 적절한 시간을 설정해야합니다.

관련 문제