我试图通过拦截对doClick(定位器)的调用来自定义Selenium的click命令的行为(通过user-extentions.js)。基本上我需要在显示应用程序的“忙碌指示符”时延迟点击操作。
(现在这种情况的标准答案是在脚本中插入waitFor用于那些情况。事实上,我们目前在整个脚本中都有数以万计。我正试图消除这些。)
检测页面元素是微不足道的部分。棘手的部分是让脚本实际等待。我看起来很有希望,但失败的尝试看起来像这样:
var nativeClick = Selenium.prototype.doClick;
Selenium.prototype.doClick = function(locator) {
this.doWaitForCondition("!selenium.browserbot.findElementOrNull('busy-indicator')", 5000);
return nativeClick.call(this, locator);
}
每次点击前都会调用doWaitForCondition,但是当条件评估为false时,它会不等待。 nativeClick总是立即被调用,因此不会引入延迟。我怀疑doWaitForCondition函数实际上并没有执行任何等待,而是在命令执行循环中为它建立条件。在这种情况下,click命令已经在播放,我正在尝试在命令中运行命令。
有人可以了解Selenium命令执行和waitFor的工作原理,或提供有关如何执行此操作的建议吗?
答案 0 :(得分:5)
我终于解决了这个问题。并且使用比尝试以各种形式拦截点击处理更好的方法。我精确的目标是:当我们的应用程序“忙”时,延迟执行脚本命令。
完成后,每个selenium命令都会返回一个ActionResult
对象(请参阅ActionHandler.prototype.execute
)。此对象上的terminationCondition
属性是一个函数,用于确定selenium何时可以继续执行下一个命令(TestLoop.prototype.continueTestWhenConditionIsTrue
)。基本上,selenium重复执行条件函数,直到它产生true。结果对象非常简单:
function ActionResult(terminationCondition) {
this.terminationCondition = terminationCondition;
}
我想在myAppIsBusy()
返回true时延迟执行。当然,所有标准延迟也需要保持不变,例如等待页面加载,以及脚本化的显式waitFor条件。解决方案是在user-extensions.js中重新定义selenium结果对象,如下所示:
function ActionResult(terminationCondition) {
this.terminationCondition = function() {
// a null terminationCondition means okay to continue
return (!terminationCondition || terminationCondition()) && !myAppIsBusy();
}
}
最棒的是,它处于足够低的水平,适用于IDE以及RC。
请注意,这不会影响Accessor或Assert命令类型,它们返回不同的结果对象。但这应该没问题,因为这些命令不会影响应用程序的状态。
答案 1 :(得分:0)
好吧,看看java驱动程序com.thoughtworks.selenium.Wait
类就会发现:
public void wait(String message, long timeoutInMilliseconds, long intervalInMilliseconds) {
long start = System.currentTimeMillis();
long end = start + timeoutInMilliseconds;
while (System.currentTimeMillis() < end) {
if (until()) return;
try {
Thread.sleep(intervalInMilliseconds);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
throw new WaitTimedOutException(message);
}
我不是要深入到selenium,但我怀疑每个waitXXX方法都指向这个。
因此,Selenium正与Thread.sleep()
合作。虽然这可能看起来不是一个理想的解决方案,但它至少表明,如果需要,你可以自己使用Thread.sleep()来减少它。 ; - )