2013-10-30 38 views
0

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

现在我知道Ajax调用和测试引擎之间的竞争问题,并且我已采取措施来保护它,但我仍然有一些问题。我的场景是这样的:我改变select元素1的值,它触发Ajax调用,删除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在退出前被添加,从而允许其下一行使用。我应该补充一点,我已经确定超时不会发生在这里(因为我的方法允许它发生),我肯定它不是这种情况

编辑:我应该补充说,把睡觉(1)myWaitForElementToAppear调用解决问题后,但我不明白为什么需要额外的第二个。不应该打电话给myWaitForElementToAppear就够了吗?

回答

1

有一些解释here

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

从php.net:

睡眠和usleep的想法是,通过让CPU运行几个空闲 周期,因此其他程序可以有自己的运行一些周期。 什么导致更好的响应时间和更低的整体系统负载。 所以如果你不得不等待的东西,去睡觉几秒钟 ,而不是占用CPU,虽然绝对没有,但 等待。

你也可以使用waitUntil出自PHPUnit:

/* 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); 
+0

我不认为那个时候是我的问题。它的唯一目的是阻止我花费更多(大约)5秒钟的时间来等待JavaScript发挥它的魔力,因为这应该足够了。此外,我并不关心释放CPU,直到我解决了主要问题,它没有在DOM中找到元素,应该已经存在。 现在,如果我正确地读取了您的代码,如果元素未找到,则返回true,这与我需要的完全相反。我需要异常不会被抛出行$ input = ... – Ajant

+0

如果你只是在发现元素(异常没有被抛出)的时候改变你的代码返回true,那么你基本上得到的功能与我的功能完全相同,不幸的是,它不适用于我,这是原因,我在这里张贴在第一位。我是否错误地阅读了你的答案? – Ajant

+0

您打电话给_myWaitForElementToAppear_,但是告诉我们_myWaitForElementToDisappear_ 只需在_ $ input = _之后移动_return true_,在我的示例中用waitUntil – rNix

相关问题