我有一个用Selenium测试的Web应用程序 . 页面加载时会运行很多JavaScript .
这段JavaScript代码编写得不是很好,但我无法改变任何东西 . 因此,等待元素以 findElement()
方法出现在DOM中不是一种选择 .
我想在Java中创建一个通用函数来等待页面加载,可能的解决方案是:
-
运行JavaScript脚本表单WebDriver并将
document.body.innerHTML
的结果存储在字符串变量body
中 . -
将
body
变量与之前版本的body
进行比较 . 如果它们相同则设置增量计数器notChangedCount
否则将notChangedCount
设置为零 . -
等待一个小时(例如50毫秒) .
-
如果页面没有改变一段时间(例如500毫秒),那么
notChangedCount >= 10
然后退出循环,否则循环到第一步 .
你认为这是一个有效的解决方案吗?
14 回答
如果有人真的知道一般的,总是适用的答案,它会在很久以前的任何地方实施,并且会让我们的生活变得更加容易 .
你可以做很多事情,但每一个都有问题:
正如Ashwin Prabhu所说,如果你对脚本有所了解,你可以观察它的行为,并在
window
或document
等上跟踪它的一些变量 . 但是,这个解决方案并不适合所有人,只能由你使用,而且只能用于有限的一组页面 .通过观察HTML代码及其是否已经有一段时间没有被更改的解决方案也不错(同样,a method直接通过
WebDriver
获取原始和未经编辑的HTML),但是:实际断言页面需要很长时间才能显着延长测试时间 .
你永远不知道正确的间隔是什么 . 该脚本可能正在下载超过500毫秒的大型内容 . 我们公司的内部页面上有几个脚本在IE中需要几秒钟 . 您的计算机可能暂时缺少资源 - 比如防病毒软件会让您的CPU完全运行,那么即使对于非复杂的脚本,500毫秒也可能太短 .
有些脚本永远不会完成 . 他们称自己有一些延迟(
setTimeout()
)并且一次又一次地工作,并且每次运行时都可能改变HTML . 说真的,每个"Web 2.0"页都做到了 . 甚至Stack Overflow . 您可以覆盖最常用的方法并考虑使用它们完成的脚本,但是......您无法确定 .如果脚本执行除更改HTML之外的其他操作,该怎么办?它可以做成千上万的事情,而不仅仅是一些乐趣 .
有一些工具可以帮助您 . 即Progress Listeners和nsIWebProgressListener以及其他一些人 . 然而,浏览器对此的支持非常糟糕 . Firefox开始尝试从FF4开始支持它(仍在不断发展),IE在IE9中有基本支持 .
我想我很快就会想出另一个有缺陷的解决方案 . 事实是 - 由于永久的脚本正在完成他们的工作,所以没有明确的答案何时说“现在页面已完成” . 选择最适合你的那个,但要注意它的缺点 .
谢谢Ashwin!
在我的情况下,我应该等待在某个元素中执行jquery插件..特别是“qtip”
根据你的提示,它对我来说非常有用:
注意:我正在使用Webdriver 2
你需要等待Javascript和jQuery才能完成加载 . 执行Javascript以检查
jQuery.active
是0
和document.readyState
是complete
,这意味着JS和jQuery加载完成 .JS库是否定义/初始化窗口上任何众所周知的变量?
如果是这样,您可以等待变量出现 . 您可以使用
((JavascriptExecutor)driver).executeScript(String script, Object... args)
测试这个条件(类似于:
window.SomeClass && window.SomeClass.variable != null
)并返回一个布尔值true
/false
.将其包装在WebDriverWait中,并等待脚本返回
true
.以下代码在我的情况下完美运行 - 我的页面包含复杂的Java脚本
来源 - How To Wait For Page To Load/Ready In Selenium WebDriver
我有同样的问题 . 这个解决方案适用于WebDriverDoku:
http://www.seleniumhq.org/docs/04_webdriver_advanced.jsp
如果你需要做的就是在尝试与元素交互之前等待页面上的html变得稳定,你可以定期轮询DOM并比较结果,如果在给定的轮询时间内DOM是相同的,你就是金色 . 你通过的地方就是这样的最大等待时间和比较前页面轮询之间的时间 . 简单有效 .
对于
nodejs
Selenium库,我使用了以下代码段 . 在我的情况下,我正在寻找添加到窗口的两个对象,在这个示例中是<SOME PROPERTY>
,10000
是超时毫秒,<NEXT STEP HERE>
是在窗口上找到属性后发生的事情 .我让我的开发人员创建了一个JavaScript变量“isProcessing”,我可以访问它(在“ae”对象中),它们在事情开始运行时设置并在事情完成时清除 . 然后我在一个累加器中运行它,每100毫秒检查一次,直到它连续五次,总共500毫秒没有任何变化 . 如果30秒过去了,我会抛出异常,因为到那时应该发生了什么 . 这是在C#中 .
要正确地执行此操作,您需要处理异常 .
这是我如何等待iFrame . 这要求您的JUnit测试类将RemoteWebDriver的实例传递给页面对象:
注意:你可以see my entire working example here .
你可以编写一些逻辑来处理这个问题 . 我已经编写了一个返回
WebElement
的方法,这个方法将被调用三次,或者你可以增加时间并为WebElement
添加一个空检查 . 这是一个例子这是我自己的代码:
Window.setTimeout仅在浏览器空闲时执行 .
因此,如果浏览器中没有活动,则递归调用函数(42次)将花费100ms,如果浏览器忙于执行其他操作则更多 .
作为奖励,可以在document.readyState或jQuery Ajax调用上重置计数器,或者如果正在运行任何jQuery动画(仅当您的应用程序使用jQuery进行ajax调用时...)
...
...
编辑:我注意到如果加载新页面并且测试可能会停止响应,则executeAsyncScript不能正常工作,而是更好地使用它 .
在找到页面上的任何元素之前,可以使用两个条件来检查页面是否已加载:
使用下面的redayState将等到页面加载
下面的JQuery将等到数据未加载
在这些JavaScriptCode尝试findOut webElement之后 .
我是这样做的: