我为什么要使用测试驱动开发?

时间:2009-04-29 22:31:02

标签: unit-testing tdd agile

重复:

对于不了解测试驱动开发的开发人员,采用TDD会解决哪些问题?

[编辑]让我们假设开发人员已经(ab)使用单元测试框架。

11 个答案:

答案 0 :(得分:20)

以下是TDD可能对开发人员/团队有所帮助的三个原因:

  • 更好地理解你要写的内容
  • 执行更好地编写测试的政策
  • 加快发展速度

首先编写测试的一个原因是在编写之前更好地理解实际代码。对我而言,这是测试驱动开发的主要好处。当您首先编写测试用例时,您会更加批判性地考虑角落情况。然后,当您编写代码并确保它们准确无误时,可以更轻松地解决这些问题。

另一个原因是实际执行写测试。通常当人们在没有TDD的情况下进行单元测试时,他们会设置测试框架,编写一些新代码,然后退出。他们认为代码已经运行得很好,为什么要编写测试呢?这很简单,它不会破坏,对吗?但是现在你已经失去了首先进行单元测试的优势(完全不同的讨论)。先写下它们,它们已经在那里了。

首先编写这些测试可能意味着您不需要在调试环境中启动程序(特别是对于较大的项目而言),以测试一些小事情是否有效。当然,在做出改变之前没有理由不这样做。

说服自己或其他人先写测试可能很困难。你可能有更好的运气让他们同时写两篇文章,这可能同样有益。

答案 1 :(得分:7)

据推测,您在将其提交到存储库之前测试了您编写的代码。

如果不是这样,你还有其他问题要处理。

如果确实如此,您可以查看使用框架编写测试作为自动化当前编写的主要例程或驱动程序的方法,这样您只需按一下按钮就可以自动运行所有这些例程或驱动程序。您不必仔细考虑输出以确定测试是通过还是失败;您将测试的成功或失败嵌入到代码中,并立即做出竖起或下降的决定。一次运行所有测试可以减少“敲打鼹鼠”的可能性,在这种情况下,您可以在一个类中修复某些内容并破坏其他内容。所有的测试都必须通过。

到目前为止听起来不错,是吗?

TDD人员要求你在写完课程之前先写下测试FIRST,这样才能更进一步。当然,它失败了,因为你没有写过这门课。这是他们保证你编写测试类的方法。

如果您已经在使用测试框架,从您编写的测试中获得良好的价值,并且有意义的代码覆盖率达到70%左右,那么我认为您做得很好。我不确定TDD会给你更多的价值。由你来决定你是否加倍努力。就个人而言,我不这样做。如果我认为有需要,我会在课后编写测试并重构。有些人可能会发现,首先编写测试会知道它会失败,但我不这样做。

答案 2 :(得分:6)

(这更像是对duffymo答案的评论,而不是自己的答案。)

duffymo回答:

  

TDD人员要求你在写完课程之前先写下测试FIRST,这样才能更进一步。当然,它失败了,因为你没有写过这门课。这是他们保证你编写测试类的方法。

我认为这实际上是迫使程序员考虑他们的代码在做什么。必须考虑测试才能考虑代码应该做什么:前置条件和后置条件是什么,哪些函数是原始的,哪些是由原始函数组成的,最小的必要公共接口是什么,以及什么是实施细节。

这些都是我经常考虑的事情,所以像你一样,“先测试”不会增加很多,对我来说。坦率地说(我知道这在某些圈子里是异端)我喜欢先勾勒出公共界面,然后“锚定”一个类的核心思想;通过这种方式,我可以看一下,精神上使用它,看看它是否像我想象的那样干净。 (类或库应该简单直观,供客户端程序员使用。)

换句话说,我做的是TDD尝试通过首先编写测试来确保发生,但是像duffymo一样,我以不同的方式实现。

“先测试”的真正意义在于让编码人员像设计师一样停下来思考。嘲笑程序员如何进入该状态是愚蠢的;对于那些不自然地做到这一点的人来说,“先测试”可以作为让他们到达那里的仪式。对于那些做过的人来说,“先测试”并没有增加太多 - 并且可能妨碍程序员习惯性地进入该状态。

同样,我们想要看结果,而不是仪式。如果一个初级人需要一个仪式,一个“十字架”或一个念珠*来“陷入困境”,“先测试”就是为了这个目的。如果有人有他们自己的方式也到那里,那也很棒。

请注意,我并不是说不应该测试代码。这应该。它为我们提供了一个安全网,这反过来又使我们能够集中精力编写好的代码,甚至是大胆的代码,因为我们知道网络可以捕获错误。

我所说的只是“先测试”的恋物癖坚持将方法(其中之一)与目标混淆,使程序员思考他的编码是什么

*为了普及,我会注意到天主教徒和穆斯林都使用念珠。再一次,它是一种机械,肌肉记忆方式,将自己置于某种心境。这是一种迷信(在原始意义上的魔法物体,而不是“性迷信”的意思)或好运的魅力。所以说“Om mani padme hum”,或者坐着zazen,或者抚摸着一只“幸运的”兔子的脚(对兔子来说不是那么幸运。)哲学家Jerry Fodor在考虑难题时也有类似的仪式:他重复一遍对自己说,“来吧,杰里,你能做到!” (我也试过了,但因为我的名字不是Jerry,所以它对我不起作用。;))

答案 3 :(得分:4)

理想情况下:

您不会浪费时间编写您不需要的功能。您将拥有一个全面的单元测试套件,作为重构的安全网。您将获得有关如何使用代码的可执行示例。您的开发流程将更加顺畅和快速;你将花更少的时间在调试器中。

但最重要的是,你的设计会更好。您的代码将更好地考虑 - 松散耦合,高度内聚 - 并且更好地形成 - 更小,更好命名的方法&类。

答案 4 :(得分:4)

对于我目前的项目(运行在相对较重的过程中),我采用了一种特殊形式的TDD,包括根据需求文档和GUI模型编写框架测试用例。在开始实现任何东西之前,我写了几十个,有时几百个(这完全违背了“纯粹的”TDD,它说你应该编写一些测试,然后立即开始进行骨架实现)。

我发现这是查看需求文档的绝佳方式。我必须更加深入地考虑他们所描述的行为,而不是仅仅是为了阅读它们。因此,我发现其中存在更多的不一致和差距,否则我将在实施过程中找到这些差异和差距。这样,我可以提前要求澄清,并在我开始实施时有更好的要求。

然后,在实施过程中,测试是一种衡量我还有多远的方法。它们阻止我忘记任何事情(不要笑,当你处理更大的用例时,这是一个真正的问题)。

道德观点是:即使你的开发过程并不真正支持TDD,它仍然可以通过某种方式完成,并提高质量和生产力。

答案 5 :(得分:3)

我个人不使用TDD,但是我能用这种方法看到的最大的专家之一是客户满意度保证。基本上,我们的想法是您的开发过程的步骤如下:

1)与客户讨论应用程序应该做什么,以及它应该如何应对不同的情况。

2)将1)的结果转换为单元测试,每个单元测试测试一个特征或场景。

3)编写简单的“草率”代码(几乎没有)通过测试。完成后,您就达到了客户的期望。

4)重构你在3)中写的代码,直到你认为你已经以最有效的方式完成它。

完成此操作后,您可以生成符合客户需求的高质量代码。如果客户现在需要一个新功能,那么就开始循环 - 讨论该功能,编写一个确保其有效的测试,编写通过测试的代码,重构。

正如其他人所说,每次运行测试时,都要确保旧代码仍然有效,并且可以添加新功能而不会破坏旧代码。

答案 6 :(得分:2)

我所谈过的大多数人并没有使用完整的TDD模型。他们通常会找到最适合他们的测试模型。找到你的TDD游戏,找到你最有效率的地方。

答案 7 :(得分:1)

我努力学习Ruby on Rails开发的TDD。我真的进入它之前需要几天时间。我非常怀疑,但我努力,因为我尊重的程序员支持它。

此时我觉得绝对值得付出努力。有几个好处,我相信其他人会很乐意为您列出。对我来说,最重要的优势在于它有助于避免项目后期出现噩梦般的情况,在这个项目中,某些东西突然中断,没有明显的原因,然后你会花一天半的时间使用调试器。它有助于防止您的代码库在向其添加越来越多的逻辑时恶化。

答案 8 :(得分:1)

TDD(测试驱动开发/设计)具有以下优点

  • 确保您在开始之前了解故事卡的验收标准
  • 确保您知道何时停止编码(即,当验收标准已满足时,从而防止镀金)

结果你得到的代码是

  1. testable
  2. 清洁设计
  3. 能够自信地重构
  4. 满足故事卡所需的最少代码
  5. 代码如何工作的生活规范
  6. 能够支持可持续发展的新功能

答案 9 :(得分:0)

众所周知,编写测试和进行大量自动化测试是件好事。

但是,如果没有TDD,它通常会变得单调乏味。人们编写测试,然后离开它,并且测试没有得到应有的更新,也没有经常测试新功能。

这很大一部分原因是代码变得很难测试--TDD会影响你的设计,因此很容易 进行测试。因为您已经使用过TDD,所以您可以进行大量的测试,这样可以在代码或需求发生变化时更容易找到回归,从而大大简化调试,从而获得良好的TDD评估,并鼓励在更改时编写更多测试需要 - 我们又回到了周期的开始。

答案 10 :(得分:-3)

有许多优点:

  • 更高的代码质量
  • 更少的错误
  • 减少浪费时间

任何这些都足以证明实施TDD。