2012-09-23 60 views
12

我有一個失敗的Rails集成測試,我不明白爲什麼。我使用硒水銀作爲司機。異步JavaScript的水豚一體化測試

在AJAX調用發生後,測試檢查頁面內容已被刪除。相關的操作是單擊一個按鈕,並且該按鈕單擊會導致頁面的一部分通過jQuery remove()調用被刪除。以下是集成測試代碼的近似值:

click_button("Remove stuff") 
assert has_no_link?("This should be removed") 

斷言失敗,意味着鏈接仍然存在。

我一直在讀水豚,我知道你可以延長默認的等待時間。我已經將它擴展到一個荒謬的價值(20秒),並且仍然斷言失敗。

當我手動按照測試過程我自己,在源頁面仍顯示的內容,但DOM不(通過查看Firefox的DOM查看和尋找的元素)。這是問題嗎?我甚至嘗試檢查DOM ,而測試在Firefox中運行,以檢查內容是否存在,並且看起來不是這樣。

我不知道Capybara是如何找到這個不再存在於DOM中的鏈接的。 Capybara檢查源代碼而不是DOM並在那裏找到鏈接?如果是這樣,我不知道如何解決這個測試,以確保測試通過。刷新頁面將解決問題,但這不完全是一個用戶會做什麼,所以我猶豫改變頁面只是爲了使測試通過...

會愛如何解決這個問題的任何建議。

謝謝!

+1

你終於找到了解決問題的辦法嗎?我有一個類似的,我想知道你是否可以對我有任何幫助。 –

+1

不幸的是,不幸的是沒有。我花了太多時間讓單個測試工作,所以我最終只是評論它而不是修復它。對不起,我無法提供更多的幫助......我已經花了很多時間,沒有精力去深入探索!隨意回答這個問題,如果你想出來,我會很樂意給你信用! – aardvarkk

+0

您是否記得在您的rspec中包含'js:true'? – RubeOnRails

回答

0

有一個簡單的方法來檢查ajax請求是否完成,我從this article瞭解到。可以使用ajax $.active函數(這是not in the actual API but is exposed,以便您可以使用它)而不是wait$.active告訴你的活動連接數的服務器,所以當它下降到零,你知道Ajax請求完成:

wait_until do 
    page.evaluate_script('$.active') == 0 
end 

如果不工作,那麼問題是在其他地方(從判斷你寫的東西似乎很可能)。如果更改只發生在DOM中,那麼您必須確保爲您的測試/規範啓用了javascript。例如,在rspec中,您設置了:js => true來執行此操作;在Cucumber中,您在@javascript之上添加一行。我不使用rails的默認測試,但是必須有一個設置來執行相同的操作。

+0

嗯...我使用的是Capybara下的Selenium驅動,它默認支持JavaScript測試(請參閱https://github.com/jnicklas/capybara#drivers)。我試着添加你的等待代碼,但沒有解決它。好主意雖然!只是還沒有解決... – aardvarkk

+0

你使用水豚的任何其他測試涉及JavaScript? –

+0

是的,但這是唯一尋找*刪除*信息的人。所有其他的東西似乎工作...例如,檢查AJAX查詢導致新的按鈕或更改內容。但是關於jQuery'remove()'的東西似乎並沒有坐好。如果我檢查'page.html',它仍然顯示那裏的內容,所以這裏肯定有問題。 – aardvarkk

0

你是第一次用鏈接測試別的東西,然後測試它被刪除了嗎?

換句話說,就是你的測試是這樣的:

has_no_link = $('#id_for_link') 
//.... some test 
click_button("Remove stuff") 
assert has_no_link?("This should be removed") 

如果是這樣的話,那麼has_no_link仍將指向的鏈接。 remove()會將它從DOM中移除,但是你的變量仍然指向它的內存。

您應該再次在DOM中查詢鏈接以查看您是否得到結果。

0

我不得不重寫wait_until進行測試,其中包含等待通過將YouTube視頻流式傳輸到特定點觸發的回調。下面是我用什麼:

# in spec_helper.rb 
require "timeout" 
def wait_until time=0.1 
    Timeout.timeout(Capybara.default_wait_time) do 
     sleep(time) until value = yield 
     value 
    end 
end 
+1

有關更多最新版本的水豚,請注意'default_wait_time'已被棄用。現在使用'default_max_wait_time'。 – Sia

0

夫婦的辦法我認爲是:

1:檢查你的水豚版本,並期待與您的版本的任何錯誤

2:也許嘗試在做一個查找按鈕後鏈接被點擊

click_button( 「刪除的東西」) 發現。(:XPath中, '//一個[文本()=' 鏈接應該刪除')應該be_false

3:使用has_link?而不是has_no_link?

click_button( 「刪除的東西」) page.has_link?( 「鏈接應刪除」)。應be_false

0

你總是可以手動執行此操作。使用@ shioyama的想法:

def wait_for_ajax 
    timer_end = Time.now + 5.seconds 
    while page.evaluate_script('$.active') != 0  
     if Time.now > timer_end 
     fail "Page took more than 5 seconds to load via ajax" 
     end 
     sleep 0.1 
    end 
    end 
3

Thoughtbot對等待AJAX​​,但它是基於Rspec的,你可以閱讀here,一個偉大的博客文章,它看起來像你正在使用TestUnit。

它適用於水豚不夠長時間等待的情況,但不會增加不必要的長時間停頓。我在Rspec的工作大多了,但我認爲你可以通過這樣修改:

# Create this file in test/support/wait_for_ajax.rb 
module WaitForAjax 
    def wait_for_ajax 
    Timeout.timeout(Capybara.default_max_wait_time) do 
     loop until finished_all_ajax_requests? 
    end 
    end 

    def finished_all_ajax_requests? 
    page.evaluate_script('jQuery.active').zero? 
    end 
end 

您可以包括它需要在各個測試文件時,或者使用this SO post自動包括所提供的策略之一它每一次。

然後,只要你有一個測試,沒有正確等待AJAX​​完成,只需插入行wait_for_ajax。以你的代碼爲例:

click_button("Remove stuff") 
wait_for_ajax 
assert has_no_link?("This should be removed")