锁定老帖子 主题:什么是“测试驱动开发”
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2006-04-24
(前面的讨论: http://forum.iteye.com/viewtopic.php?t=19959 http://forum.iteye.com/viewtopic.php?t=20035) 看“测试驱动开发”这个名字,首先应该明确:与它对应的是“文档驱动开发”。它是一种开发过程,这里的测试是一个设计问题,而不是QA问题。在没有TDD之前,“正统的”开发过程要求有设计文档:高层设计描述一个模块“做什么事”,详细设计描述一个模块“如何做这些事”。软件工程课讲得清楚,只有源代码的软件不能算软件,因为它不可理解、不可维护;源代码加上文档,才算是程序员完整地交付了自己的工作。要做任何一件事之前,你必须首先清楚地知道自己要做什么(以及不要做什么),否则那就是crack,不是在从事职业的软件开发。 但这种文档有几个致命的缺陷。第一,自然语言的描述容易产生歧义;第二,不能自动化地验证;第三,不能保证文档与程序同步。测试驱动开发正是为了解决这些问题而产生的。在编写一段代码之前你所写的测试,不是为了确保这段代码不出错,而是为了描述你想要做的事情。当你拥有这个测试之后,持续集成会始终确保你的代码恰好是做了你想要做的事情。测试驱动开发是一种设计方法,它清晰无二义地描述你的设计,并保证设计与实现一致。 所以几个典型的问题就可以很清楚地找到答案。单元测试要不要是白盒的?要。因为你是在描述如何实现这个模块,而不是验证它的输入输出正确性。单元测试要不要把每个模块放到真实的事务或者并发环境下测试?不要。因为你只是描述当前模块的实现,真实环境下的正确性由集成测试和QA来保证。为什么模块内部实现的变化要同时导致测试变化?因为你的思路、你的设计变化了,你应该有一个文档描述这件事情。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2006-04-24
重构一个组件时,是
先按照新的设计修改对应的单元测试,然后修改组件的实现使其通过所有(包括那个新的)测试, 还是 直接修改组件的实现,如果新的实现能通过所有测试,重构成功,否则宣布重构失败,继续修改? 或者说以上两种做法哪个才是真正的重构? |
|
返回顶楼 | |
发表时间:2006-04-24
TDD是修改功能代码之前,先修改测试来表达你的实现方式,然后运行测试,fail,再修改功能代码,再运行测试,直到测试通过,则证明你的修改完成。
|
|
返回顶楼 | |
发表时间:2006-04-24
daquan198163 写道 重构一个组件时,是
先按照新的设计修改对应的单元测试,然后修改组件的实现使其通过所有(包括那个新的)测试, 还是 直接修改组件的实现,如果新的实现能通过所有测试,重构成功,否则宣布重构失败,继续修改? 或者说以上两种做法哪个才是真正的重构? 第二个 我知道你后面的问题是什么,不过请你先提出来,我们接着讨论。 |
|
返回顶楼 | |
发表时间:2006-04-24
robbin 写道 TDD是修改功能代码之前,先修改测试来表达你的实现方式,然后运行测试,fail,再修改功能代码,再运行测试,直到测试通过,则证明你的修改完成。
同意,增加或修改一个功能度时确实要这样。 不过我前面问的是“另一顶帽子”——重构 |
|
返回顶楼 | |
发表时间:2006-04-24
我的这个问题你还没解答,呵呵,是在那个帖子里的。
我 写道 我不同意你的地方是:代码也是文档,它是比单元测试更加详细的设计文档;
那么,如果"单元测试文档"细到了和"代码文档"一样的水平,是不是就重复了? 我觉得mack测试的问题就是太细了,于是就引出我上面的问题和前面的另一个重构问题: 用mock测试符合TDD的直觉吗?(我在为一个组件写测试时,想得更多的是它从外面看起来是什么样子,而不会去想也还想不清楚它里面会有哪些机关) 我又有些新的认识,"单元测试文档"更像是详细需求文档,他要描述“做什么”,而不是“怎么做”,“怎么做”还是要在(并且应该只在)"代码文档"中描述。 |
|
返回顶楼 | |
发表时间:2006-04-24
我没去听演讲,看来我错过了提问题的机会,我这里提一个问题:
清楚的代码能反映设计, 测试代码能反映设计。 两者不重复了嘛? 如果一个清晰的设计已经浮现了,先写漂亮的代码,还是埋头先写测试呢? |
|
返回顶楼 | |
发表时间:2006-04-24
算法的设计和实现,TDD适合嘛?
|
|
返回顶楼 | |
发表时间:2006-04-24
gigix 写道 daquan198163 写道 重构一个组件时,是
先按照新的设计修改对应的单元测试,然后修改组件的实现使其通过所有(包括那个新的)测试, 还是 直接修改组件的实现,如果新的实现能通过所有测试,重构成功,否则宣布重构失败,继续修改? 或者说以上两种做法哪个才是真正的重构? 第二个 我知道你后面的问题是什么,不过请你先提出来,我们接着讨论。 那么,在mock测试与代码实现重复的反映了设计的情况下,重构势必导致原有单元测试失败,重构无法进行下去,因为你已经不能保证重构没有破坏原有功能。 是否会出现这种情况? 如果有,Spring有大量的mock测试,它是怎么解决的? |
|
返回顶楼 | |
发表时间:2006-04-24
daquan198163 写道 gigix 写道 daquan198163 写道 重构一个组件时,是
先按照新的设计修改对应的单元测试,然后修改组件的实现使其通过所有(包括那个新的)测试, 还是 直接修改组件的实现,如果新的实现能通过所有测试,重构成功,否则宣布重构失败,继续修改? 或者说以上两种做法哪个才是真正的重构? 第二个 我知道你后面的问题是什么,不过请你先提出来,我们接着讨论。 那么,在mock测试与代码实现重复的反映了设计的情况下,重构势必导致原有单元测试失败,重构无法进行下去,因为你已经不能保证重构没有破坏原有功能。 是否会出现这种情况? 如果有,Spring有大量的mock测试,它是怎么解决的? 举个例子来说,LoginController调用UserDAO.loadByName()方法,这个逻辑你用mock来描述了。这是你怎么重构都不会影响到的。如果你重构来重构去,闹到不调用这个方法了,或者调用了两次,那么这就已经是改变了功能实现,不仅仅是重构了。 |
|
返回顶楼 | |