Selenium会等待JavaScript完成吗?

前端之家收集整理的这篇文章主要介绍了Selenium会等待JavaScript完成吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用 Java / Selenium测试 JavaScript API.

我在Java端发出这些命令,

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

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

  1. function setName(msg) {
  2. // simulate async call
  3. setName(function(){name = msg;},1000);
  4. }

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

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

谢谢

解决方法

您可以轻松地要求Selenium等到特定条件成立;在你拥有的,一个替代方案是:
  1. new FluentWait<JavascriptExecutor>(executor) {
  2. protected RuntimeException timeoutException(
  3. String message,Throwable lastException) {
  4. Assert.fail("name was never set");
  5. }
  6. }.withTimeout(10,SECONDS)
  7. .until(new Predicate<JavascriptExecutor>() {
  8. public boolean apply(JavascriptExecutor e) {
  9. return (Boolean)executor.executeScript("return ('Hello' === getName());");
  10. }
  11. });

但是,那么你基本上测试的是你刚刚编写的内容,并且缺点是如果在调用setName之前设置了name,则不必等待setName完成.我过去做过类似事情的一件事是:

在我的测试库中(用setTimeout垫片替换真正的异步调用),我有这个:

  1. window._junit_testid_ = '*none*';
  2. window._junit_async_calls_ = {};
  3. function _setJunitTestid_(testId) {
  4. window._junit_testid_ = testId;
  5. }
  6. function _setTimeout_(cont,timeout) {
  7. var callId = Math.random().toString(36).substr(2);
  8. var testId = window._junit_testid_;
  9. window._junit_async_calls_[testId] |= {};
  10. window._junit_async_calls_[testId][callId] = 1;
  11. window.setTimeout(function(){
  12. cont();
  13. delete(window._junit_async_calls_[testId][callId]);
  14. },timeout);
  15. }
  16. function _isTestDone_(testId) {
  17. if (window._junit_async_calls_[testId]) {
  18. var thing = window._junit_async_calls_[testId];
  19. for (var prop in thing) {
  20. if (thing.hasOwnProperty(prop)) return false;
  21. }
  22. delete(window._junit_async_calls_[testId]);
  23. }
  24. return true;
  25. }

在我的库的其余部分,每当我需要设置稍后发生的事情时,我使用_setTimeout_而不是window.setTimeout.然后,在我的硒测试中,我做了这样的事情:

  1. // First,this routine is in a library somewhere
  2. public void waitForTest(JavascriptExecutor executor,String testId) {
  3. new FluentWait<JavascriptExecutor>(executor) {
  4. protected RuntimeException timeoutException(
  5. String message,Throwable lastException) {
  6. Assert.fail(testId + " did not finish async calls");
  7. }
  8. }.withTimeout(10,SECONDS)
  9. .until(new Predicate<JavascriptExecutor>() {
  10. public boolean apply(JavascriptExecutor e) {
  11. return (Boolean)executor.executeScript(
  12. "_isTestDone_('" + testId + "');");
  13. }
  14. });
  15. }
  16.  
  17. // Inside an actual test:
  18. @Test public void serverPingTest() {
  19. // Do stuff to grab my WebDriver instance
  20. // Do this before any interaction with the app
  21. driver.executeScript("_setJunitTestid_('MainAppTest.serverPingTest');");
  22. // Do other stuff including things that fire off what would be async calls
  23. // but now call stuff in my testing library instead.
  24. // ...
  25. // Now I need to wait for all the async stuff to finish:
  26. waitForTest(driver,"MainAppTest.serverPingTest");
  27. // Now query stuff about the app,assert things if needed
  28. }

请注意,如果需要,您可以多次调用waitForTest,只要您需要该测试暂停,直到完成所有异步操作.

猜你在找的JavaScript相关文章