另一个WebDriverException:元素不再附加到DOM

时间:2013-10-30 14:46:47

标签: php jquery ajax selenium-webdriver

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

现在我知道Ajax调用和测试引擎之间的竞争问题,我已采取措施保护它,但我仍然有一些问题。我的场景是这样的:我更改了触发Ajax调用的select元素1的值,删除了select元素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就足够了吗?

1 个答案:

答案 0 :(得分:1)

有一些解释here

  

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

来自php.net:

  

睡眠和睡眠的想法是让cpu运行一些闲置   循环,所以其他程序可以有自己的一些循环。   是什么导致更好的响应时间和更低的整体系统负载。   所以如果你不得不等一下,就去睡觉几秒钟   而不是占用cpu,而绝对没有   waitting。

您可以使用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);