java - Does Selenium wait for JavaScript to complete? - Stack Overflow

I am testing a JavaScript API using JavaSelenium.I issue these mands on Java side,executor.executeScri

I am testing a JavaScript API using Java/Selenium.

I issue these mands on Java side,

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

In JavaScript side, this is an async function, so it is supposed to take some time and set the variable.

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

I need to wait for this async function to plete before moving to the next line in Java, where the assertEquals() is executed.

Is there any way to acplish this without using Thread.sleep() on Java side.

Thanks

I am testing a JavaScript API using Java/Selenium.

I issue these mands on Java side,

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

In JavaScript side, this is an async function, so it is supposed to take some time and set the variable.

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

I need to wait for this async function to plete before moving to the next line in Java, where the assertEquals() is executed.

Is there any way to acplish this without using Thread.sleep() on Java side.

Thanks

Share Improve this question edited Apr 14, 2014 at 5:00 toniedzwiedz 18.6k10 gold badges89 silver badges135 bronze badges asked Apr 14, 2014 at 1:09 ecthelion84ecthelion84 3562 gold badges5 silver badges14 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 2

You can easily ask Selenium to wait until a particular condition is true; in exactly what you have, one alternative would be:

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

However, then you're basically testing exactly what you just coded, and that has the disadvantage that if name were set before you called setName, you haven't necessarily waited setName to finish. One thing I've done in the past for similar things is this:

In my testing library (which replaces real async calls with setTimeout shims), I have this:

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

In the rest of my library, I use _setTimeout_ instead of window.setTimeout whenever I need to set something up to happen later. Then, in my selenium test, I do something like this:

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

Note that you can call waitForTest multiple times if needed, any time you need that test to pause until all async operations are finished.

I doubt selenium does. It only waits for page to be pletely loaded, but not a script to finish. You may wish to define your own 'test step' for waiting for result (and constantly polling the page contents/script state), but be sure to setup reasonable timout not to male your tests hang forever on script error.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744337940a4569229.html

相关推荐

  • java - Does Selenium wait for JavaScript to complete? - Stack Overflow

    I am testing a JavaScript API using JavaSelenium.I issue these mands on Java side,executor.executeScri

    7天前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信