2012-02-09 38 views
15

方案斷言一個特定的異常在黃瓜拋出

我正在寫一個庫(沒有Ruby on Rails的),我想爲它有非常詳細的黃瓜功能。這尤其包括描述在各種情況下應該拋出的錯誤/異常。

最直觀的方式來寫黃瓜步驟可能會是這樣的

When I do something unwanted 
Then an "ArgumentError" should be thrown 

問題

有兩個問題,我必須解決:

  1. 當引發異常時,第一步不應該失敗。
  2. 第一步引發的異常應該可以通過第二步訪問,以便執行某些斷言魔術。

Unelegant和繁瑣的解決方案

我已經能夠拿出的緩存例外的第一步,把它變成一個實例變量,第二步驟後才能訪問的最佳方法,像這樣:

When /^I do something unwanted$/ do 
    begin 
    throw_an_exception! 
    rescue => @error 
    end 
end 

Then /^an "(.*)" should be thrown$/ do |error| 
    @error.class.to_s.should == error 
end 

然而,這使得第一步或多或少沒用的情況下,我希望它失敗,它需要一個實例變量,這是從來沒有一件好事。

那麼,任何人都可以幫助我至少減少繁瑣的解決方案嗎?還是應該以不同的方式寫我的功能?任何幫助將非常感激。

+0

現在,這個問題寫得很好!肯定值得一個好的答案(對不起,我不能拿出一個):) :) – user562529 2012-03-08 02:24:11

+0

非常感謝@ user562529。不幸的是我有這樣的感覺,實際上這個問題實際上並沒有簡單的解決方案,所以我可能只是打開一個黃瓜問題,並希望他們實施一些實用的東西。 – JLimperg 2012-03-08 21:43:29

回答

5

我想過這個問題再一次,也許答案是:

沒有很好的解決方案,因爲Given-When-Then -Scheme在您的案件中侵犯。 你期望「那麼應該拋出異常」是「當我做一些不需要的東西時」的結果。

但是,當你想到它,這是不正確的!這個例外不是這個動作的結果,實際上這個例外只是表明「When」 - 語句失敗。

我到該溶液中。將在更高層次上進行測試:

When I do something unwanted 
Then an error should be logged 

When I do something unwanted 
Then the user should get an error message 

When I do something unwanted 
Then the program should be locked in state "error" 

或這些的組合。

然後,您將在程序中「緩存異常」 - 這非常有意義,因爲無論如何您最有可能需要這樣做。

你說過的兩個問題也會解決。

如果你真的必須測試異常

嗯,我想那麼黃瓜是不正確的測試套件,嗯? ;-)

由於考慮 - 當 - 當時的方案是違反無論如何,我只想寫

When I do something unwanted it should fail with "ArgumentError" 

和步驟的定義是這樣(未經測試,請糾正我,如果你嘗試)

When /^I do something unwanted it should fail with "(.*)"$/ do |errorstring| 
    expect { 
    throw_an_exception! 
    }.to raise_error(errorstring) 
end 

如上所述,這是可怕的錯誤,因爲計劃被打破,但它會達到目的,不是嗎? ;-)

您將在測試錯誤at rspec expectations處發現更多文檔。

+0

噢,我剛剛讀了你的第一句話。不要介意,當你寫作一個圖書館時,答案或多或少是無用的。 – user562529 2012-03-13 15:51:14

+1

感謝您的廣泛寫作。不幸的是,你的評論也碰到了頭。 ;) 但是,你說的話可能仍然是正確的,並且與這個問題有關:Cucumber可能只是爲了深入挖掘圖書館的錯誤處理而設計的。好像我會堅持使用RSpec解決這個問題。 – JLimperg 2012-03-25 15:54:16

+0

我遇到了同樣的問題,並得出結論,雖然Cucumber是一個偉大的庫用於測試應用程序,但它不太適合測試庫。 Cucumber最大的優勢在於它可以被沒有閱讀代碼的人閱讀,很少有非開發人員可能有興趣閱讀開發人員庫的規範,所以我已經在Cucumber上爲應用程序和RSpec定義了庫。 對於像我這樣的人在開發應用程序時發現這個頁面,這是一個很好的答案。在這種情況下,在更高層次上編寫規範更合適。 – 2013-02-10 16:23:50

4

一種方法是用@allow-rescue標記場景並檢查頁面的輸出和狀態代碼。例如

my_steps.rb

Then(/^the page (?:should have|has) content (.+)$/) do |content| 
    expect(page).to have_content(content) 
end 

Then(/^the page should have status code (\d+)$/) do |status_code| 
    expect(page.status_code.to_s).to eq(status_code) 
end 

Then /^I should see an error$/ do 
    expect(400..599).to include(page.status_code) 
end 

my_feature.feature

​​

或者:

@allow-rescue 
Scenario: Make sure user can't do XYZ 
    Given some prerequisite 
    When I do something unwanted 
    Then I should see an error 

這可能不是正是你所希望看到的,但它可能是一個對於遇到此頁面的某些人可接受的解決方法。我認爲這將取決於異常類型,因爲如果異常在任何級別都沒有獲救,那麼該場景仍然會失敗。我已經使用這種方法主要用於路由錯誤到目前爲止,這工作得很好。

-1

我是從誰的人在行爲驅動開發情況使用黃瓜功能的角度回答,所以要麼接受,要麼離開它...

方案應寫入測試「功能」或功能的應用程序,而不是用於測試代碼本身。一個例子是:

When the service is invoked 
Then a success code should be returned 

這聽起來像你的測試用例(即如果我這樣做,那麼這個異常應該拋出)可以單位或集成測試的候選人 - 在我的情況下,我們會使用一些嘲弄或單元測試框架。

我的建議是重新評估你的功能場景,看看他們是否真的在測試你想要測試的東西。從個人經驗來看,我發現如果我的測試課變得異常複雜,那麼我的功能是錯誤的。

1

可以在When塊中引發異常,然後在以下Then塊中對其作出斷言。

使用你的例子:

When /^I do something unwanted$/ do 
    @result = -> { throw_an_exception! } 
end 

Then /^an "(.*)" should be thrown$/ do |error| 
    expect{ @result.call }.to raise_error(error) 
end 

這個例子使用RSpec的匹配器,但重要的部分是->(波長);這允許參考throw_an_exception!方法傳遞。

我希望有幫助!