2010-11-05 101 views
14

我們使用Selenium和Java API以及一些Javascript用戶擴展。我們在我們的應用中使用了很多AJAX調用。我們的很多測試都會隨機失敗,因爲有時AJAX調用會比其他時間更慢,因此頁面未完全加載。我們通過等待特定元素或Thread.sleep來解決這個問題。我試圖找到一種方法,而不是等待網絡流量完成。所以,我們可以這樣做:Selenium - 等待網絡流量

selenium.click("some JS button"); 
selenium.waitForNetwork(); 
assertTrue(something); 

這樣,我們可以擺脫線的睡眠,並有測試通過更快當服務器響應速度更快,不會有這麼多的測試失敗,由於時間問題。

我一直無法找到一種方法來搜索Google。有沒有人有任何想法,我們可以做到這一點? (最好通過Javascript或Java API但歡迎所有建議)。

注意:「waitFor」的其他變體不是我正在尋找的。我們已經在點擊和其他方面使用了這些功能。我正在尋找等待網絡流量的東西。感謝所有的反饋,我會嘗試一些建議,但我仍然接受其他想法。

謝謝。

回答

2

更新:我用同樣的方法(wrapRequest)與Selenium2相同,它仍然有效。唯一的區別是我不使用用戶擴展。我只是執行JavaScript來查詢由JSP加載的代碼。

這就是我們最終做的。 (注意,如果你總是隻使用像JQuery這樣的單個框架,那麼有更簡單的方法來獲得Ajax調用是否正在運行,因爲我們有幾個使用JQuery和一堆的頁面使用GWT)

我創建了一個JavaScript文件,每個頁面只在你正在測試時加載。 (我通過在我們的JSP模板中包含一個片段來做到這一點:如果測試查詢字符串參數被傳入爲真,請設置一個cookie。如果設置了該cookie,請包含JavaScript文件) 此JavaScript文件基本上包裝XMLHttpRequest對象以保留所有發送請求的計數:

function wrapRequest(xmlRequest) { 
    var oldSend = xmlRequest.prototype.send; 
    xmlRequest.prototype.send = function() { 
     var oldOnReady = this.onreadystatechange; 
     oldOnReady = function() { 
      oldOnReady.apply(this, arguments); 
      // if call is complete, decrement counter. 
     } 
     // increment counter 
     if(oldSend.apply) 
      oldSend.apply(this, arguments); 
     else if (oldOnReady.handleEvent) { //Firefox sometimes will need this 
      oldOnReady.handleEvent.apply(this, arguments); 
     } 
    } 
} 

還有一點,比如果async == false,但應該很容易弄清楚。

然後,我增加了一個功能,硒用戶extensions.js,僅僅是這樣的:

Selenium.prototype.getIsNetworkReady = function() { 
    if(this.browserbot.topWindow.isNetworkReady) { //sometimes this method is called before the page has loaded the isNetworkReady function 
     return this.browserbot.topWindow.isNetworkReady(); 
    } 
    return false; 
} 

另外,還要注意對topWindow檢查:這是因爲當選擇一個iframe你的問題。

此外,您將不得不調用每個加載的iFrame的XMLHttpRequest對象上的wrapRequest方法。我現在使用:document.addEventListener("DOMNodeInserted", onElementAdded, true);,然後在onElementAdded中,我只是在加載iframe時傳入XMLHttpRequest對象。但在IE中不起作用,所以我正在尋找替代方案。如果有人知道更好的方式來做到這一點,所以它在IE和FF都有效,我很樂意聽到它。

無論如何,這是實施的要點。希望這有助於任何人在未來。

0

是,做這樣的事情(僞):

int i = 0; 
while (element is not yet present) { 
    i++; 
    if (i>TRESHOLD) { 
    throw an exception 
    } 
    Thread.sleep(200); 
} 
//go on 

您propably想把它塞進一個功能。

4

Selenium中有幾種可用的waitFor類型。在你的測試案例中,如果你知道一個特定的文本會出現在頁面加載中,你可以使用waitForText。如果有不同的DOM元素被填充(通過Ajax/pageload),您可以順序添加waitForText。

1

我們已經有客戶端代碼在AJAX請求期間(使用a4j:status,屬性爲onstartonstop)更改鼠標光標。因此,我們可以簡單地等待JavaScript表達式的值

window.document.body.style.cursor 

但是,我發現這不能可靠地工作,即有時測試進行得太早。我不確定原因,但懷疑當調用onstop時,更新DOM並不一定完全完成。爲了減少不必要的延遲,您可以自己實施輪詢,並且比硒更頻繁地輪詢輪詢。

4

嘗試此頁面上描述的所有變化後,我們結束了這一戰略:

注入一個特殊的JavaScript,基本上覆蓋所有的相關框架的方法和保持計數器未完成的請求數的,在開始時遞增並在完成時遞減。由於JavaScript的異步特性,它不是而是足以保留一個布爾變量,您可能最終在自己的邏輯中出現競爭條件。

如果您使用的是視覺效果,您可能也希望爲視覺效果做到這一點;變形/褪色等視覺效果會有同樣的問題。

所以我們基本上做了一個常規的「點擊」,然後總是等待這個計數器再次達到0,使用JavaScript很像其他人在這裏所建議的。在我們完成這項工作後,我們將短暫問題減少到無。

請記住,硒不會從「點擊」返回,直到所有同步onclick事件都被處理完畢,所以您必須確保讓這些計數器增加爲onclick的直接結果。

有關如何覆蓋框架方法的說明,您需要查閱您的框架文檔;我們在原型中使用addMethods。可以將這個覆蓋保存在一個特殊的JavaScript中,只有在運行測試時纔會添加到頁面中。

+0

對於我們內部構建的AJAX框架,我們做了同樣的事情,在WaitForCondition()中調用IsTheCountZeroYet()函數。我明白你可以輕鬆地用jQuery來做到這一點。其他框架,也許也是。 – 2010-11-11 22:07:08

+0

有趣的是,prototype.js中的ajax計數器是越野車,它們並不總是返回0。視覺效果還沒有這種類型的計數器。所以我們必須推出自己的。 – krosenvold 2010-11-13 19:21:57