2010-08-30 59 views
1

假设我们正在设计一个Stack类测试第一(TDD):关于几个问题的单元测试

public class Stack<T> { 
    private T[] elements = new T[16]; 
    private int size = 0; 
    ... 
} 

这个堆栈利用了大小16个内部数组来存储它的元素。它会正常工作,直到你需要添加第17个元素。因为我可能需要第17个元素,所以我决定将该功能添加到我的堆栈中,所以我开始考虑可以给测试添加哪些名称,以便添加该功能。这将是我的第一个问题的主题。

我首先选择的形式的东西:

Should_Be_Able_To_Correctly_Increase_Its_Inner_Array_Size() 

然后

Should_Handle_More_Items_Than_The_Default_Internal_Array_Size() 

但想了一会儿后,我得出的结论,也许像下面这样会比较apropriate :

Should_Double_Its_Size_Every_Time_Its_Full() 

我的推理必须在第一种情况下这样做,我说只有它做什么,但不是什么时候。 第二,我说什么时候添加更多的项目,但我也说明我是如何在内部实现它的,这可能是不正确的。在我看来(我不确定我是否正确),我的测试应该是我的SUT与外部可能的相互作用,而不是内部如何实现。我对吗?

它在我看来,第三个选项是最好的,因为它清楚地说明了它的作用(增长的规模 - 事实上,它的大小的两倍),当它(当它已满),并没有联系我到任何特定的实现(我可能以后可能想要将其更改为内部ArrayList!)。

这使我对我的第二个问题:假设我做了所有的单元测试我的Stack类在内部使用数组和它工作正常,符合预期,应我的测试中保持不变,如果我以后要重构并将数组更改为ArrayList或任何其他类型的数据结构?还是应该以任何方式反映这些测试?我猜不,但我不确定。

+0

对我来说似乎你的测试不应该对内部工作做出假设。如果稍后您选择更改某些内部实现细节,则不需要重写所有测试。 – Mark 2010-08-30 19:12:01

回答

3

在我看来(我不知道我 正确的),我的测试应该我SUT的可能 相互作用与 外部,而不是它是如何 内部实现。我对吗?

你是对的。如果你改变你的类的内部实现,单元测试应该保持不变。如果您在外部暴露任何新内容,则应该创建新的单元测试来说明这些更改。

请记住,当你设计你的课程时,你不想公开任何表明它是如何实现的。班上的公共成员指出如何与它互动,现在它在幕后如何运作。

2

我不知道如何通过单元测试来测试内部列表或数组大小。您无法通过堆栈接口访问它。单元测试用于测试外部合同。如果你想测试实现细节,那么尝试其他的东西。

第二个问题的答案是肯定的,如果是单元测试,测试仍然应该通过。

+0

当做这个类的TDD风格时,我会做什么样的测试呢? – 2010-08-30 20:06:02

+0

测试外部接口并确保它按预期工作。 – 2010-08-31 05:26:59

1

我不确定应该通过单元测试测试内部列表或数组大小,因为您无法通过堆栈接口访问它。实现堆栈的方法有很多,有些很好,有些很糟糕,但正如Bernard所说,这些是内部实现。单元测试旨在测试外向功能。

2

问问你自己,你愿意为这门课承担什么。

您或班级的消费者真的关心容量是否增加一倍或增加一千?如果是这样,你应该修改界面,让他们可以指定用于增加容量的策略:

public Stack<T>(CapacityGrowthStyle capacityGrowthStyle) { ... } 

如果没有,只是写测试记录的能力,并留在这一点(其中下面X是基础数据结构的限制):

[Test] 
public void Can_Handle_X_Items() { ... } 

[Test] 
[ExpectedException(typeof(InvalidOperationException))] 
public void Cannot_Handle_More_Than_X_Items() { ... } 

我会回答你的第二个问题类似:你的测试应该只反映底层数据结构,如果你的类的用户会在意它。

+0

我明白了你的观点。现在,如果我遵循TDD指南,我应该如何添加这个“功能”?现在我明白了,那是我的主要问题! – 2010-08-30 20:07:23

+1

@devoured - 这是一个有趣的(和困难的)问题。如果容量增长算法对我的用户来说真的很重要(推测是出于性能原因),我会试图添加一个'容量'属性来促进测试,即使用户可能通常不需要该属性。但是我会对API的混乱感到一些遗憾。 ( – 2010-08-30 20:30:29

+0

)但是让我们说,我的用户不会想知道它。使用测试优先方法,我应该只添加一些特定的功能,如果我先测试它的测试,但在这种情况下,我会如何解决这个问题? – 2010-08-30 20:41:44