2014-04-14 9 views
7

Testuję JavaScript API przy użyciu Java/Selenium.Czy Selenium czeka na zakończenie JavaScript?

I wydawać te polecenia na stronie Java,

executor.executeScript("setName('Hello');"); 
// Thread.sleep(2000); 
String output = (String)executor.executeScript("return getName()"); 
assertEquals(output, "Hello"); 

w bok JavaScript, jest to funkcja asynchroniczne, więc ma trochę czasu i ustawić zmienną.

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

muszę czekać na to, aby zakończyć funkcję asynchronicznych przed przejściem do następnego wiersza w Javie, gdzie assertEquals() jest wykonywany.

Czy jest jakiś sposób, aby to osiągnąć bez korzystania z Thread.sleep() po stronie Java.

Dzięki

Odpowiedz

2

Możesz łatwo poprosić Selenium, aby poczekał, aż dany warunek będzie prawdziwy; w dokładnie to, co masz, jeden alternatywą byłoby:

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

Jednak wtedy jesteś w zasadzie testowania dokładnie to, czego po prostu zakodowane, i że ma tę wadę, że jeśli name były ustawione przed nazywa setName, ci Haven” t koniecznie czekał setName, aby zakończyć. Jedną rzeczą, jaką zrobiłem w przeszłości podobnych rzeczy to:

W moim testowania biblioteki (który zastępuje rzeczywistą asynchronicznie wzywa z setTimeout podkładek), mam to:

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

W pozostałej części mojego biblioteki, używam _setTimeout_ zamiast window.setTimeout, gdy chcę ustawić coś, co stanie się później. Następnie, w moim teście selenu, zrobić coś takiego:

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

pamiętać, że można zadzwonić waitForTest wielokrotnie w razie potrzeby, za każdym razem trzeba, że ​​test, aby wstrzymać, aż wszystkie operacje asynchroniczne są wykończone.

0

Wątpię, aby selen miał. Czeka tylko na pełne załadowanie strony, ale nie na skrypt. Możesz chcieć zdefiniować swój własny "krok testowy", aby poczekać na wynik (i stale odpytuje zawartość strony/stan skryptu), ale upewnij się, że ustawiłeś rozsądnie na czas nie męski, twoje testy zawieszają się na zawsze na błędach skryptu.

Powiązane problemy