2013-12-12 23 views
1

我目前正在使用SpecFlow學習/測試BDD,並且它非常棒!可能在BDD中沒有一個場景嗎?

我選擇要問我的問題之前,我已經閱讀this one,我覺得我不得不問我的問題,儘管同樣的問題,是因爲它沒有提及Exception方案的解決。

我實際測試這樣的場景:

Scenario: I should get an error whenever I try to remove an item from an empty stack 
    Given I have an empty stack 
    When I pop from it 
    Then I should get an error 

public class StackBehaviour { 
    public void GivenIHaveAnEmptyStack() { stack = new CustomStack<string>(); } 

    // This will throw whenever called! 
    // So the Then method will never be run! 
    // I feel like I should just put a comment which says why it's empty, 
    // allowing a fellow programmer to understand the exact intention. 
    public void WhenIPopFromIt() { stack.Pop(); } 

    // It is here that it verifies whether the CustomStack meets the expected behaviour. 
    public void ThenIShouldGetAnError() { 
     Assert.Throws<IndexOutOfRangeException>(delegate { 
      stack.Pop(); 
     }); 
    } 

    private CustomStack<string> stack; 
} 

public class CustomStack<T> { 
    public T Pop() { 
     if (stack.Count == 0) 
      throw new IndexOutOfRangeException("Cannot pop from an empty stack!"); 
     T item = stack[stack.Count-1]; 
     stack.RemoveAt(stack.Count-1); 
     return item; 
    } 

    private ArrayList stack = new ArrayList(); 
} 

我認爲留在When方法的評論是正確的,使業務需求並不缺少任何信息,並在後面的代碼,我通過評論清楚地說明了我的意圖。

您認爲如何?任何其他的想法,爲什麼我不應該做它?

+0

提供的答案都很棒!我現在很難選擇哪一個作爲我的問題的答案,因爲這些問題的解決方式不同,並且兩種答案都可以彼此相同。首先,我知道我想要一個錯誤,所以只需編碼'When'即可。我完全同意!其次,諸如在堆棧上推零的技術問題應該與利益相關者無關,因爲它更可能是技術問題,並且這引出了BDD和TDD之間的界限。我完全同意! –

+0

@Alski答案確實顯示瞭如何使用SpecFlow來測試這個CustomStack,但是我仍然認爲使用BDD框架來隔離測試單個組件是過度的。 BDD通常用於描述用戶如何與系統交互;在您的示例中,用戶不會直接從堆棧中彈出某個項目,而是在應用程序中執行一個操作,該操作使用CustomStack,然後觸發堆棧彈出。因此,我認爲使用TDD和單元測試可以更好地測試CustomStack。看看Alski的想法會很有趣。 –

+0

我完全同意,新鮮。在現實世界中,BDD代表整個系統的行爲測試。正因爲如此,嚴格說BDD,你的答案是最好的解決方案。除此之外,Alski的答案滿足了教程的需要,也就是說,能夠同時使用'When'和動作發生的地方'Then',它將在那裏與期望的值/行爲進行測試。我的困境就在於阿爾斯基的回答暗示了什麼,這解決了我的問題,實際上我們看到了BDD和TDD之間的界線,因爲事實上,這些例外不屬於BDD,而是屬於TDD。 –

回答

2

還有一個竅門,您可以用在綁定幫助要素的意思更清晰一點。在這種情況下,讓我們從最後開始。

Then I should get an error 

你的問題基本在這裏,你知道想要一個錯誤,但你不知道如何得到它。事實上,你已經錯過了,錯誤已經發生在When步驟中,並且在你的代碼示例中,你將該行爲移動到了then步驟,以便您可以獲取該錯誤。

但如果保持when的表演動作AMD什麼重新表達我們then反映到底發生了什麼

Then I should have had an error 

似乎是一個微不足道的變化,但現在我們的特點,反映了誤差應已與When相關我們只是在稍後評估它,這是我們可以編碼的東西。我們只需要記住when中的錯誤並將其發送到then

private Exception errorFromWhen = null; 

public void WhenIPopFromIt() 
{ 
    try 
    { 
    stack.Pop(); 
    } 
    catch(Exception ex) 
    { 
    errorFromWhen = ex; 
    } 
} 

public void ThenIShouldGetAnError() 
{ 
    errorFromWhen.ShouldNotBeNull(); 
    errorFromWhen.ShouldBe<IndexOutOfRangeException>(); 
} 

SpecFlow實際上已經由於其mini Dependency injection system絕對沒有問題,這一點,你甚至可以在必要時通過綁定類之間的這種狀態。

+0

+1感謝您的回答,這絕對有意義!我會考慮這一點並立即嘗試。 –

1

可能的情景沒有在BDD什麼時候?

在Specflow,既不給定,當或然後是強制性的。

然而,在你的榜樣,我不相信這是一款很好用Specflow和BDD的。在這個答案在這裏馬庫斯說:

"BDD is about ensuring that we're building the right thing, TDD is about ensuring that we're building it right."

在您的例子,現在被測試即CustomStack範圍,應通過TDD進行測試。使用CustomStack的最終解決方案應該通過BDD(以及SpecFlow)進行測試,例如如果這個CustomStack是通過某個網站上的特定操作來執行的。

This答案,它也有助於你的問題。

+0

+1感謝這些見解。我將理所當然地認爲單元測試項目仍然適用於BDD。這畫出了不在​​BDD和TDD之間交叉的線。除此之外,我正在關注這篇測試堆棧行爲的有趣文章,讓我們說利益相關者需要一個堆棧對象,所以我想知道哪一行不能跨越。 http://www.ibm.com/developerworks/java/library/j-cq09187/index。html –

+0

感謝您的回答。我真的很瞭解它。請參閱我的最後一條評論與我的問題相關,以便您可以知道我是如何接受Alski的答案的。如果您覺得我的判斷有問題,請隨時說出來,我會考慮重新考慮我的接受程度。 –

相關問題