Selenium waitFor机制的内部工作原理是什么?

时间:2010-11-16 14:26:26

标签: javascript extensibility internals selenium-ide

我试图通过拦截对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的工作原理,或提供有关如何执行此操作的建议吗?

2 个答案:

答案 0 :(得分:5)

我终于解决了这个问题。并且使用比尝试以各种形式拦截点击处理更好的方法。我精确的目标是:当我们的应用程序“忙”时,延迟执行脚本命令。

Selenium命令处理的工作原理:

完成后,每个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()来减少它。 ; - )