1

我目前正在使用 SpecFlow 学习/测试 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方法中留下注释是正确的,这样业务需求就不会缺少任何信息,并且在后面的代码上,我通过注释明确了我的意图。

你怎么看?任何其他想法为什么我不应该这样做?

4

2 回答 2

2

您可以使用另一个技巧,绑定有助于使功能的含义更加清晰。在这种情况下,让我们从最后开始。

Then I should get an error

你的问题基本上在这里,你知道想要一个错误,但你不知道如何得到它。实际上,您已经错过了它,错误已经发生在When步骤中,并且在您的代码示例中,您将操作移动到then步骤中,以便您可以得到错误。

但是,如果继续when执行该动作并重新表达我们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 对此绝对没有问题,事实上,由于它的迷你依赖注入系统,如果需要,您甚至可以在绑定类之间传递此状态。

于 2013-12-13T16:46:37.933 回答
1

BDD 中的场景可能没有When 吗?

在 Specflow 中,既没有给出,也没有给出,何时或然后都是强制性的。

但是在您的示例中,我不认为这是对 Specflow 和 BDD 的良好使用。在这个答案中,马库斯说:

“BDD 是关于确保我们正在构建正确的东西,TDD 是关于确保我们正在正确地构建它。”

在您的示例中,应通过 TDD 测试正在测试的范围,即 CustomStack。它是使用 CustomStack 的最终解决方案,应该通过 BDD(以及因此 SpecFlow)进行测试,例如,如果这个 CustomStack 是通过网站上的某个操作来执行的。

这个答案也与您的问题有关。

于 2013-12-13T00:20:02.363 回答