将单元测试视为测试特定功能而不是特定方法通常更有效率。任何给定的测试都将检查某些方法集合是否正确地实现了作为测试主题的功能,并且设计良好的一组测试中的失败模式往往会告诉您哪个方法很快就崩溃了。
大量的测试往往会自然而然地脱离 TDD;这是使这项技术如此强大的原因之一。如果我正在写 a Deque
,我写的测试往往如下,通常按此顺序呈现。
empty_Deque_isEmpty
-- 实现isEmpty
总是返回true
non_empty_Deque_isntEmpty
-- 实现insertFirst
使isEmpty
实例变量为假
re_emptied_Deque_isEmpty
-- 将使用的实例变量更改isEmpty
为响应insertFirst
和的数字removeFirst
is_empty_Deque_size_correct
-- 实现size
始终返回 0
is_nonempty_Deque_size_correct
-- 添加实例变量以跟踪大小;意识到它正在做同样的事情isEmpty
;重构
is_re_emptied_Deque_size_correct
-- 让测试通过,因为我们做了什么来实现 5. 发生
does_removing_from_empty_Deque_throw
--在做任何其他事情之前removeFirst
需要检查size
is_inserted_item_returned
--insertFirst
现在removeFirst
填充一个T
实例变量
is_inserted_item_returned_from_end
-- 加上removeLast
那是一个副本removeFirst
;重构
is_rear_inserted_item_returned
-- 添加insertLast
该副本insertFirst
;重构
are_all_inserted_items_returned
——改变insertFirst
并removeFirst
采取行动SomeKindOfCollection<T>
;不检查检索顺序
does_removeFirst_retrieve_items_in_correct_order
-- 插入两个东西,确保第二个由removeFirst
. 可能已经是真的了。
does_removeLast_retrieve_items_in_correct_order
- 同上removeLast
,除非很确定不会通过。
这是一大堆测试,但是当您查看它们时,您应该注意到其中的模式。这些测试都不是真正的“测试count
”或“测试removeFirst
”。但是当我们完成时,该类的整个接口都在运行,并且该接口所需的所有内部组件都已开发完毕。一些测试依赖于不止一种方法,如果该方法失败,它们都会中断。但是中断的模式往往会非常有助于确定错误在哪里。
同样有趣的是,我们可以通过多少这些测试而无需承诺在对象中实际拥有一个集合,这表明可以将这组测试分解成一个更通用的测试套件,这在开发PriorityQueue
.