单元测试 - 我做得对吗?

bar*_*ron 16 c# collections tdd unit-testing

基本上我已经编程了一段时间,在完成我的上一个项目之后可以完全理解如果我做完TDD会有多容易.我想我仍然没有严格执行,因为我仍然在编写代码,然后为它编写测试,如果你不知道什么结构以及你的存储数据等,我不太清楚测试在代码之前的变化... 但无论如何...

有点难以解释,但基本上可以说例如我有一个具有id,颜色和成本等属性的Fruit对象.(全部存储在textfile中完全忽略任何数据库逻辑等)

    FruitID FruitName   FruitColor  FruitCost
    1         Apple       Red         1.2
    2         Apple       Green       1.4
    3         Apple       HalfHalf    1.5
Run Code Online (Sandbox Code Playgroud)

这只是一个例子.但是我要说这是这个结构中的Fruit(它是a List<Fruit>)对象的集合.如果水果被删除,我的逻辑会说要重新排序集合中的fruitids(这就是解决方案需要的方式).

例如,如果删除1,则对象2采用水果ID 1,对象3采用水果id2.

现在我想测试我编写的代码进行重新排序等.

如何设置它来进行测试?


这是我到目前为止的地方.基本上我有所有方法的fruitManager类,如deletefruit等.它通常有列表,但我已经改变了hte方法来测试它,以便它接受一个列表,并删除水果上的信息,然后返回列表.

明智的单元测试:我基本上是以正确的方式做到这一点,还是我的想法错了?然后我测试删除不同的有价值的对象/数据集,以确保方法正常工作.


[Test]
public void DeleteFruit()
{
    var fruitList = CreateFruitList();
    var fm = new FruitManager();

    var resultList = fm.DeleteFruitTest("Apple", 2, fruitList);

    //Assert that fruitobject with x properties is not in list ? how
}

private static List<Fruit> CreateFruitList()
{
    //Build test data
    var f01 = new Fruit {Name = "Apple",Id = 1, etc...};
    var f02 = new Fruit {Name = "Apple",Id = 2, etc...};
    var f03 = new Fruit {Name = "Apple",Id = 3, etc...};

    var fruitList = new List<Fruit> {f01, f02, f03};
    return fruitList;
}
Run Code Online (Sandbox Code Playgroud)

gui*_*e31 12

如果您没有看到应该从哪个测试开始,可能是您没有想到您的功能应该用简单的术语来做什么.试着想象一下预期的基本行为的优先级列表.

您对Delete()方法的第一件事是什么?如果您在10分钟内发送删除"产品",那么包含哪些不可谈判的行为?嗯......可能是它删除了元素.

所以:

1) [Test]
public void Fruit_Is_Removed_From_List_When_Deleted()
Run Code Online (Sandbox Code Playgroud)

当编写该测试时,请完成整个TDD循环(执行test => red;编写足够的代码使其通过=> green; refactor => green)

与此相关的下一个重要事项是,如果作为参数传递的水果不在列表中,则该方法不应修改列表.所以接下来的测试可能是:

2) [Test]
public void Invalid_Fruit_Changes_Nothing_When_Deleted()
Run Code Online (Sandbox Code Playgroud)

您指定的下一件事是,在删除水果时应重新排列ID:

3) [Test]
public void Fruit_Ids_Are_Reordered_When_Fruit_Is_Deleted()
Run Code Online (Sandbox Code Playgroud)

放在那个测试中的内容是什么?好吧,只需设置一个基本但有代表性的上下文,它将证明您的方法符合预期.

例如,创建一个包含4个水果的列表,删除第一个水果并逐个检查3个剩余水果ID是否正确重新排序.这很好地涵盖了基本情景.

然后,您可以为错误或边缘情况创建单元测试:

4) [Test]
public void Fruit_Ids_Arent_Reordered_When_Last_Fruit_Is_Deleted()

5) [Test]
[ExpectedException]
public void Exception_Is_Thrown_When_Fruit_List_Is_Empty()
Run Code Online (Sandbox Code Playgroud)

...


Pét*_*rök 7

在您真正开始编写第一个测试之前,您应该对应用程序的结构/设计,接口等有一个大致的了解.设计阶段通常与TDD有关.

我想对于一个经验丰富的开发人员来说,这很明显,并且在阅读问题规范后,他立即开始在他/她的头脑中看到解决方案的设计 - 这可能是为什么它通常被视为理所当然的理由.但是,对于经验不足的开发人员来说,设计活动可能需要更加明确.

无论哪种方式,在第一个设计草图准备就绪后,TDD既可用于验证行为,也可用于检查设计本身的可靠性/可用性.你可能会开始编写你的第一个单元测试,然后意识到"哦,用我想象的界面做这个实际上很尴尬" - 然后你回去重新设计界面.这是一种迭代方法.

Josh Bloch在"Coders at Work"中讨论了这个问题 - 他甚至开始实现任何东西之前就为他的接口编写了很多用例.因此,他勾勒出界面,然后编写在他能想到的所有不同场景中使用它的代码.它还不具备可编辑性 - 他只是用它来感受他的界面是否真的有助于轻松完成任务.

  • @baron,我的意思是重新设计界面以使其更好.单元测试是这方面的特定客户.如果一个接口很难用于单元测试,它(几乎总是)意味着它也很难用于其他客户端. (4认同)