我对实施TDD时的常见问题的看法

发表于:2009-05-07来源:作者:点击数: 标签:tddTDDTdd看法实施
在最近发表的一篇文章《实施 TDD 时的常见问题》中, Chad Meyers提出了关于TDD实施的问题,如下所示: 1. 我该容忍多大限度的预先设计?你怎么知道应该何时停止(也就是说,“当人们开始讨论算法,就是该 测试 的时机了”)? 2. 对于象“我心里清楚我们需要
 在最近发表的一篇文章《实施TDD时的常见问题》中, Chad Meyers提出了关于TDD实施的问题,如下所示:
        1. 我该容忍多大限度的预先设计?你怎么知道应该何时停止(也就是说,“当人们开始讨论算法,就是该测试的时机了”)?
        2. 对于象“我心里清楚我们需要这个”这类东西——我们该如何处理(例如,在控制台main()方法中加上一个try/catch{Console.WriteLine(ex);}?)
        3. 编写测试时,为了让代码编译通过,你不得不写下一两个接口,一个实体类,在类中还有一些NotImplementedExceptions等等。这一步该走多远?
        4. 如果在测试一个用户故事期间,你发现先前的预先设计有问题,你是会马上停下来跟你的搭档讨论,做该做的事,然后继续;还是折返回去,在当前的故事中采用完整的测试优先模式?
        5. 在处理一个新的用户故事时,你发现针对前一个故事所编写的测试已经不再体现需求。你是否会立刻重构那个测试,还是把它标记为“忽略”,等你完成当前的故事再回过头去处理那个被忽略的测试?还是有其它做法?
        6. 如果新的用户故事要求对某个已有的测试做出轻微调整,你是会调整它,还是会写一个新测试,把旧的扔掉(也就是,“不许更改现有的测试代码!”,或者“只有出现小的编译问题时才准动它,否则就别碰!”)?
        7. 如果你构建了模型并且通过了测试,但是你发现这个设计很幼稚,而且即将要做的用户故事肯定会对其进行重大修改,并生成一个新的完全不同的模型。你是应该退 一步,考虑进行大型重构吗?还是应该继续修修补补,调整现有的模型,尽管这个模型最终会被目前看来显然超出该用户故事范围的工作所改进?

        Derick Bailey分享了他对Chad这些问题的看法。以下是他的回答的摘录:
        1. 知道自己应该构建什么就行。
        这个问题实际上应该根据你的实际项目来回答。我最近做了一个企业集成项目,里面用到了我们的核心维护系统,然后添加了一些离线操作功能。在这个项目中,我 没有做太多的预先设计。我知道系统需要能够在离线模式下操作,我还知道即使是没人登录计算机或者运行这个软件时,它也需要能够执行一些操作,我知道它需要 跟主维护系统进行双向通信,用来执行与维护相关的的一定数量的任务。我从一些设想/预先设计开始动手——构建了一个Windows Service来运行核心进程,构建了一个客户端-服务器架构来托管UI,在一个消息系统上为通信提供支持。除了这些算是预先设计以外,在构建软件的过程 中都是其他各项任务的功能需求来驱动项目设计的进展。
        最近,我与一个为实验室开发某系统的团队一起工作时,有了截然相反的体验。我们有源于客户的需求,客户所要求的流程,以及对客户手中数据进行转换的需要; 我们需要一个大规模的预先设计,用以判断我们的解决方案可以满足数据转换和功能需求。系统的核心设计是预先完成的,但是具体实现还是在开发过程中慢慢成 型。
        2. 这 是一个让我在心里做斗争的问题,回答它需要视出现这个问题的时机。我并不希望添加特性和功能,除非我知道现在需要它们——当这个问题涉及到应用程序的域模 型和核心基础架构时。然而,对于类似于Console.WriteLine(ex)之类的问题,要将这些功能添加到应用程序的Main方法中,我认为没有 什么好争论的。毕竟——你并不会对应用程序的Main方法做单元测试……你会对它进行集成测试
        3. 对于实现接口,我并不希望手动地编写桩 对象。相反,我会试着尽可能使用RhinoMocks,这样就能避免这一问题。我过去习惯于在任何时候都要编写桩代码,其中包括十几个未实现的方法——结 果导致我的单元测试难以维护,同时还为确定的单元测试中确定的方法提供了大量的重复桩对象。

        你应该只添加你需要的方法。如果你拥有一个真实的对象,它包含了将要抛出的未实现的异常,你可能要检查一下这个方法,看它是否能够从代码库中删除。
        4. 这一问题仍然要视具体的问题而定。

        我花了很多时间和我的合作者开展结对编程。我们不断遇到这样一个场景,即下一个功能需求会导致现有设计的改变。如果发生了这样的事情,我们只会对我们需要的 部分进行修改。我们会为某些新功能编写新的单元测试,如果之前的设计使得我们的单元测试无法通过,我们就会返回修改之前的设计——对在修改范围内的单元测 试进行修改与更新。我们要将在这种情况之下的单元测试看作是“必做列表”中的内容。当我们修改已经完成的设计时,我们通常会忘记这个已经修改的范围,或者 忘记我们试图满足的新的功能需求。所幸,通过对整个单元测试套件的完整运行,可以显示被破坏的测试,提醒我们需要修改。


原文转自:http://www.ltesting.net