Selenium会等待JavaScript完成吗?

时间:2014-04-14 01:09:41

标签: java javascript selenium

我正在使用Java / Selenium测试JavaScript API。

我在Java端发布这些命令,

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

在JavaScript方面,这是一个异步函数,所以它需要一些时间并设置变量。

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

我需要等待这个异步函数完成,然后再转到Java中的下一行,执行assertEquals()

如果不在Java端使用Thread.sleep(),有没有办法实现这一目标。

由于

2 个答案:

答案 0 :(得分: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());");
  }
});

然而,那么你基本上是在测试你刚编码的内容,而且有一个缺点,即如果在你调用name之前设置了setName,你就不必等待{{1} } 完成。我过去做过类似事情的一件事是:

在我的测试库中(用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; } 而不是_setTimeout_。然后,在我的硒测试中,我做了类似的事情:

window.setTimeout

请注意,如果需要,您可以多次调用// 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 } ,只要您需要该测试暂停,直到所有异步操作都完成。

答案 1 :(得分:0)

我怀疑硒的确如此。它只等待页面完全加载,但不是要完成的脚本。您可能希望定义自己的测试步骤&#39;等待结果(并不断轮询页面内容/脚本状态),但一定要设置合理的时间,而不是男性,你的测试会永远挂起脚本错误。