【发布时间】:2017-04-05 13:34:38
【问题描述】:
基于对 BDD 的一些简单阅读,我得出的结论是,单元测试是测试应用程序某些细粒度部分的好工具,而 BDD 是更高级别的,您可以在其中练习功能工作流。
我会考虑单元测试候选的一些项目:排序算法、状态缩减器、几何计算等......
我认为 BDD 候选人的项目将是功能工作流:将项目添加到购物车、登录、搜索网站内容以查找课程资料等...
一个客户要求我写一个排序算法,通常我会写一个单元测试,比如:
public class SorterTest
{
[TestMethod]
public void TestSort()
{
var numbers = new List<int>() { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
var expected = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var sorter = new Sorter()
{
Input = numbers
};
var sorted = sorter.Sort();
CollectionAssert.AreEqual(expected, sorted.ToList());
}
}
但是,客户要求进行 BDD 测试,所以我想出了以下内容:
Feature: Sort
In order to to ensure sorting of integers
I want to be able to sort a collection of integers
Scenario Outline: Perform a sort
Given I have these integers: '<input>'
When I sort them
Then the result should be '<expected>'
Examples:
| input | expected |
| 9,8,7,6,5,4,3,2,1 | 1,2,3,4,5,6,7,8,9 |
为了使我的 Sorter 对象可用于 BDD 测试,我必须对其进行更改:
private Sorter sorter = new Sorter();
[Given(@"^I have the following integers: '(.*)'$")]
public void GivenIHaveTheFollowingIntegers(string numbers)
{
var inputs = numbers.Split(',')
.Select(s => Convert.ToInt32(s.Trim()))
.ToList();
sorter.Input = inputs;
}
注意使用Given 设置测试,我必须将Input 属性添加到Sorter tp 为排序做准备。缺点是在应用程序代码中,如果我想让我的排序器执行排序,我总是需要在执行排序之前设置这个属性:
sorter.Input = intCollection;
var result = sorter.sort();
我宁愿只拥有:
var result = sorter.sort(intCollection);
BDD 适合这种测试吗?如果是这样,我做得对吗?添加Input 属性感觉不对,我应该用其他方式吗?
如果不合适,如何在 BDD 和单元测试之间划清界限?有一个existing SO post,但答案参考了一本书。如果能得到一些更好的指导,那就太好了。
【问题讨论】:
-
关于作为属性的输入。这种设计有什么特殊原因吗?我宁愿提供 Input 作为 Sort 方法的参数。
-
@TheoLenndorff 这就是我帖子的关键——我必须添加一个
Input属性来设置Given中的测试。我同意这感觉很尴尬,但我不知道我还能如何设置我的 BDD 测试。 -
简而言之:行为测试在应用程序级别进行测试,单元测试在组件级别进行测试。您通常不会为排序方法编写行为测试;你会写行为测试,例如对于一个 UI 功能,它会测试整个应用程序堆栈(或至少到一些明确定义的边界)。
-
@Mister Epic:明白。我认为在When步骤中实例化被测系统(SUT)并没有错。在 Given 步骤中提供所有输入很重要。无需为了测试而强制生产代码进行奇怪的设计。
-
@Mister Epic:哦……我想我明白你的理由了。 Sorter 类应该设计为无状态的。恕我直言,在 When 步骤中实例化无状态类没有问题。如果它有意义并且该类具有某种状态,那么在您尝试过的 Given 步骤中实例化它可能会很有用。对于集成测试尤其如此。
标签: c# unit-testing automated-tests bdd