0

我有一个包含一些 JavaScript 并执行一些 Ajax 调用的网页。尝试使用 Selenium 对其进行测试时,我随机收到“PHPUnit_Extensions_Selenium2TestCase_WebDriverException:元素不再附加到 DOM”消息,可能在 5 次运行中出现一次。

现在我知道了 Ajax 调用和测试引擎之间的竞争问题,并且我已经采取措施保护它,但我仍然有一些问题。我的场景是这样的:我更改了选择元素 1 的值,这触发了 Ajax 调用,该调用删除了选择元素 2 的所有选项子元素,并根据 Ajax 响应生成新的选项子元素。测试代码:

    $this->select($this->byId('select1'))->selectOptionByValue('value1');
    $this->myWaitForElementToAppear('#select2>option[value="value2"]');
    $this->select($this->byId('select2'))->selectOptionByValue('value2');

最后一行触发错误。这是 myWaitForElementToAppear 方法:

public function myWaitForElementToAppear($selector, $limit = 5) {
    $start = time();
    while(true) {
        if($start + $limit < time()) {
            break;
        }
        try {
            $this->byCssSelector($selector);
            break;
        } catch(PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {}
    }
}

如果我没记错的话,myWaitForElementToAppear 方法应该确保 jQuery 在退出之前添加了所需的选项,从而允许在下一行使用它。我应该补充一点,我已经确保这里不会发生超时(因为我的方法允许它发生)并且我很肯定情况并非如此

编辑:我应该补充一点,在 myWaitForElementToAppear 调用之后放置 sleep(1) 可以解决问题,但我不明白为什么需要额外的秒数。不应该调用 myWaitForElementToAppear 就足够了吗?

4

1 回答 1

1

这里有一些解释:

首先, time() 的精度非常低,只返回经过的整秒数,这使得整个事情变得非常模糊。其次,PHP 在等待时必须坐在那里循环数千次,基本上什么都不做。一个更好的解决方案是使用两个脚本睡眠函数之一,sleep() 和 usleep(),它们将暂停执行的时间量作为它们唯一的参数。

来自 php.net:

sleep 和 usleep 的想法是通过让 cpu 运行几个空闲周期,以便其他程序可以有自己的一些周期运行。什么会导致更好的响应时间和更低的整体系统负载。因此,如果您必须等待某些事情,请睡几秒钟,而不是在等待时什么都不做,而不是占用 cpu。

您可以使用PHPUnit 中的waitUntil

/* waitElementToDisappear */
$this->waitUntil(function($testCase) {
    try {
        $input = $testCase->byCssSelector("#select2>option[value="value2"]");
    } catch (PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {
        if (PHPUnit_Extensions_Selenium2TestCase_WebDriverException::NoSuchElement == $e->getCode()) {
            return true;
        }
    }
}, 5000);

/* waitElementToAppear */
$this->waitUntil(function($testCase) {
    try {
        $input = $testCase->byCssSelector("#select2>option[value="value2"]");
        return true;
    } catch (PHPUnit_Extensions_Selenium2TestCase_WebDriverException $e) {}
}, 5000);
于 2013-11-01T10:24:37.260 回答