Selenium WebDriver:等待带有JavaScript的复杂页面加载

我有一个Web应用程序用Selenium进行测试。有很多JavaScript在页面加载上运行。
这个JavaScript代码写得不是很好,但我不能改变任何东西。因此,等待元素出现在 DOM with 方法中不是一个选项。
我想在Java中创建一个泛型函数来等待页面加载,一个可能的解决方案是:findElement()

  • 运行 WebDriver 中的 JavaScript 脚本,并将 的结果存储在字符串变量 中。document.body.innerHTMLbody
  • 将该变量与以前版本的 进行比较。如果它们相同,则设置增量计数器,否则设置为零。bodybodynotChangedCountnotChangedCount
  • 等待一个短暂的时间(例如50毫秒)。
  • 如果页面在一段时间内(例如500毫秒)没有更改,那么退出循环,否则循环到第一步。notChangedCount >= 10

你认为这是一个有效的解决方案吗?


答案 1

如果有人真的知道一个通用且始终适用的答案,那么它早在很久以前就会在任何地方实施,并将使我们的生活变得更加轻松。

你可以做很多事情,但每一件事都有一个问题:

  1. 正如Ashwin Prabhu所说,如果你对脚本了如指掌,你就可以观察它的行为,并跟踪它的一些变量。但是,此解决方案并不适合所有人,只能由您使用,并且只能在有限的一组页面上使用。windowdocument

  2. 通过观察HTML代码以及它是否已经或未更改一段时间的解决方案并不坏(此外,有一种方法可以直接通过以下方式获取原始和未编辑的HTML),但是:WebDriver

    • 实际断言页面需要很长时间,并且可能会大大延长测试时间。
    • 你永远不知道什么是正确的间隔。该脚本可能正在下载一些需要超过 500 毫秒的大内容。我们公司的内部页面上有几个脚本,在IE中需要几秒钟。您的计算机可能暂时缺乏资源 - 假设防病毒软件可以使您的CPU完全工作,那么即使对于不复杂的脚本,500毫秒也可能太短。
    • 有些脚本永远不会完成。他们以一些延迟()调用自己,并一次又一次地工作,并且每次运行时都可能更改HTML。说真的,每个“Web 2.0”页面都会这样做。甚至堆栈溢出。您可以覆盖最常用的方法,并将使用它们的脚本视为已完成,但是...你不能确定。setTimeout()
    • 如果脚本执行更改 HTML 以外的其他操作,该怎么办?它可以做成千上万的事情,而不仅仅是一些乐趣。innerHTML
  3. 有一些工具可以帮助您做到这一点。即 Progress Listeners 以及 nsIWebProgressListener 和其他一些。但是,浏览器对此的支持是可怕的。Firefox从FF4开始尝试支持它(仍在发展中),IE在IE9中具有基本的支持。

我想我很快就能想出另一个有缺陷的解决方案。事实是 - 对于何时说“现在页面已完成”没有明确的答案,因为永恒的脚本在做他们的工作。选择最适合您的一个,但要注意它的缺点。


答案 2

谢谢阿什温!

在我的情况下,我应该需要等待某些元素中的jquery插件执行。特别是“qtip”

基于你的提示,它非常适合我:

wait.until( new Predicate<WebDriver>() {
            public boolean apply(WebDriver driver) {
                return ((JavascriptExecutor)driver).executeScript("return document.readyState").equals("complete");
            }
        }
    );

注意:我使用的是 Webdriver 2


推荐