代码之家  ›  专栏  ›  技术社区  ›  Joel

Selenium-等待网络流量

  •  16
  • Joel  · 技术社区  · 14 年前

    我们将Selenium与Java API和一些Javascript用户扩展一起使用。我们在应用程序中使用了很多AJAX调用。我们的很多测试都是随机失败的,因为有时候AJAX调用比其他时间完成得慢,所以页面没有完全加载。我们通过等待特定元素或Thread.sleep来解决这个问题。我正试图找到一种方法来代替只是等待网络流量结束。所以我们可以这样做:

    selenium.click("some JS button");
    selenium.waitForNetwork();
    assertTrue(something);
    

    这样我们就可以摆脱线程休眠,当服务器响应更快时测试通过得更快,而且不会因为时间问题而导致太多测试失败。

    我没办法在谷歌上搜索。有人知道我们怎样才能做到这一点吗?(最好通过Javascript或Java API,但欢迎所有建议)。

    注意:“waitFor”的其他变体不是我要找的。我们已经在点击和其他东西中使用了这些。我在找等待网络流量的东西。谢谢你的反馈,我会尝试一些建议,但我仍然对其他想法持开放态度。

    谢谢。

    6 回复  |  直到 14 年前
        1
  •  4
  •   ch4nd4n    14 年前

    硒中有几种waitFor。在您的测试用例中,如果您知道页面加载中将显示特定文本,则可以使用waitForText。如果有不同的DOM元素被填充(通过Ajax/pageload),您可以顺序添加waitfortex。

        2
  •  4
  •   krosenvold    14 年前

    注入一个特殊的javascript,它基本上覆盖了所有相关的框架方法,并保持 未完成请求的数目,开始时递增,完成时递减。由于javascript的异步特性,它是 足够保持一个布尔变量,你很可能在你自己的逻辑中以竞争条件结束。

    所以我们基本上会定期“点击”,然后总是等待这个计数器再次达到0,使用javascript,就像这里其他人建议的那样。在我们把这个放好之后,我们把暂时的问题减少到了零。

    请记住,在处理所有同步onclick事件之前,selenium不会从“click”返回,因此必须确保这些计数器作为onclick的直接结果而递增。

        3
  •  2
  •   Joel    13 年前

    更新:我使用相同的方法(wrapRequest)与Selenium2使用相同的方法,它仍然有效。唯一的区别是我不使用用户扩展。我只是执行javascript来查询JSP加载的代码。

    (注意,如果始终只使用JQuery这样的单个框架,那么如果Ajax调用正在运行,则有更简单的方法获取。我们不得不让jimmy对它进行更多的修改,因为我们有一些使用JQuery的页面和一些使用GWT的页面)

    我创建了一个Javascript文件,每个页面都只在测试时加载。(我在JSP模板中包含了一个片段:如果测试querystring参数作为true传入,则设置一个cookie。如果设置了cookie,请包含javascript文件)

    function wrapRequest(xmlRequest) {
        var oldSend = xmlRequest.prototype.send;
        xmlRequest.prototype.send = function() {
            var oldOnReady = this.onreadystatechange;
            oldOnReady = function() {
                oldOnReady.apply(this, arguments);
                // if call is complete, decrement counter.
            }
            // increment counter
            if(oldSend.apply)
                oldSend.apply(this, arguments);
            else if (oldOnReady.handleEvent) { //Firefox sometimes will need this
                oldOnReady.handleEvent.apply(this, arguments);
            }
        }
    }
    

    如果async==false,它的功能会更强大一些,但这应该很容易理解。

    Selenium.prototype.getIsNetworkReady = function() {
        if(this.browserbot.topWindow.isNetworkReady) { //sometimes this method is called before the page has loaded the isNetworkReady function
            return this.browserbot.topWindow.isNetworkReady();
        }
        return false;
    }
    

    另外,请注意topWindow上的复选框:这是因为选择iframe时会出现问题。

    此外,还必须对加载的每个iFrame的XMLHttpRequest对象调用wrapRequest方法。我现在用的是: document.addEventListener("DOMNodeInserted", onElementAdded, true);

    总之,这就是实现的要点。希望这对将来的任何人都有帮助。

        4
  •  1
  •   meriton    14 年前

    我们已经有了在AJAX请求期间更改鼠标光标的客户端代码(使用 a4j:status 具有属性 onstart onstop

    window.document.body.style.cursor
    

    然而,我发现这并不可靠,即有时测试进行得太早。我不确定原因,但怀疑当 顶部 被调用。

        5
  •  1
  •   Sergii Pozharov    14 年前

    这对你来说可能是不可接受的,但由于我们搬到了类似的问题 Selenium 2 PageFactory AjaxElementLocatorFactory

    为了简化迁移,有一个 Selenium Emulation 计划将Selenium 1和WebDriver完全合并,这是Selenium 2的主要目标。

        6
  •  0
  •   Martijn Courteaux    14 年前

    int i = 0;
    while (element is not yet present) {
      i++;
      if (i>TRESHOLD) {
        throw an exception
      }
      Thread.sleep(200);
    }
    //go on
    

    你肯定想把它塞进函数里。