如何编写TDD测试的启发式方法:从期望开始 - qwan

banq


首先从编写测试的最后一部分开始:从期望(或断言)开始,然后自下而上编写测试。
在最后开始测试,期望(或断言)的位置可能会让人感到奇怪。您可能倾向于从上到下编写测试,从设置到调用生产代码,再到期望。从期望开始可能会感觉不对。
把它想象成写一份报告——你可能记得在学校时必须写报告:一个好的方法是先写下结论,然后写下报告的其余部分,得出这些结论。从期望开始编写测试的工作方式类似。
 
关注结果
首先关注期望意味着关注期望的结果。有时这比所需的设置代码更容易表达。您还会更清楚地注意到设置代码中的重复。
从期望开始比仅仅复制粘贴之前的测试并更改一些行更难。它迫使您从一开始就考虑所需的行为和界面。你突然必须清楚地说明你的工作目标。
从期望中,我们向后工作以完成测试。我们编写最低要求的设置和代码以获得我们的结果。
 
效果
我们强迫自己先陈述我们的意图,这有助于思考设计。这提供了一个低成本、快速的反馈循环,帮助我们明确我们想要去的地方。
感觉错误和尴尬是可以的。从期望开始,我们在您的日常工作中注入一些刻意练习。
将测试重点放在结果上,有助于减少四处游荡的测试、混乱和不必要的设置代码。我们创建直接达到
他们目标的测试。
 
遗留代码
您可能认为这不适用于遗留代码。恰恰相反:虽然陈述结果可能更难,但它会帮助您为现有代码识别更好、更简洁、更集中的接口。最初的投资可能很大,但做完之后会增加理解和解脱的感觉。
 
进一步阅读
从期望开始的想法来自 Kent Beck 的Test Driven Development, By Example;他描述了一种称为Assert First的模式。
jMock,第一个模拟对象库,促成了这种思维方式。它迫使我们在测试中首先编写预期的调用。这起初是违反直觉的,但它确实迫使我们在编写代码来设置测试之前考虑我们期望的交互。
下面是Steve Freeman、Nat Pryce、Tim Mackinnon 和 Joe Walnes 的Mock Roles,not Objects 中的一个片段来说明这个想法:
public class TimedCacheTest {
  public void testLoadsObjectThatIsNotCached() {
    // we expect to call load
   
// exactly once with the key,
   
// this will return the given value
    mockLoader.expect(once())
      .method(
"load").with( eq(KEY) )
      .will(returnValue(VALUE));
    ...

实际上,jMock 强迫我们工作Then -first,所以我们得到 Then-When-Given或Then-Given-When代替通常的模式 Given-When-Then,或者我们不需要太多设置, 只是Then-When。我们首先考虑所需的交互、API 的命名方式、传入的参数、返回的内容以及与谁交互。
更多地从外在思考,我们经常使用Chris Matts 的“为了<实现某种价值>”的故事格式,正如 Elizabeth Keogh 在RIP 中所描述的那样作为一个......我想要......所以......
In order to <achieve some value>
As a <role>
I want <some feature>.

在这里,我们也从(高层)期望开始。