2013-10-30 40 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

相關問題