用简单的术语解释TDD

时间:2010-07-14 12:35:54

标签: tdd

当我遇到this问题时,我正在浏览StackOverflow。在这里,作者提到了他/她的调试风格:

  

我想知道如何进行调试。目前我遵循的步骤是,

     
      
  • 我完成了一个大脚本,
  •   
  • 评论除我要检查的部分之外的所有内容
  •   
  • 执行脚本
  •   

并且在其中一个答案中,另一个用户说提问者正在以错误的方式调试:

  

你的序列似乎完全倒退了。我是这样做的:

     
      
  1. 我为我想要的功能编写了一个测试。
  2.   
  3. 我开始编写脚本,执行位并验证测试结果。
  4.   
  5. 我回顾了我为记录和发布所做的工作。
  6.   

我对编程很新,我遵循第一种做事方式。似乎第二种方式称为测试驱动开发,它似乎是一种非常低效的做事方式。

你能以更简单的方式解释 TDD及其优点吗?

9 个答案:

答案 0 :(得分:4)

这里有两件事混杂在一起。测试驱动开发和单元测试。您不必同时执行这两项操作 - 首先编写集成测试称为ATDD或BDD,并在代码编写单元测试后编写单元测试 - 但它们可以很好地协同工作。

单元测试是关于测试小部分代码(通常是单个方法,但单元是灵活的野兽)并单独测试它。采用上面我们最初的两种方法,这会将其改为:

  • 我完成了[大型脚本的一部分]
  • 我写的测试只打到了我觉得有问题的区域
  • 执行测试

这意味着你不会乱砍你的剧本,因此不要冒险忘记取消注释。您还有一个可以再次运行的测试。这意味着您可以合理地确定新更改不会重新启用此错误。这是一个大问题;只运行一次的测试是没用的。测试应该是可重复的,并且这是代码部分代码无法解决的问题。

测试驱动开发就是在编写代码之前编写测试。这确实增加了很大的开销,但是你认为什么时候修复bug最便宜?当你写这段代码或几个月后?这是我使用TDD的主要原因。在我编写代码时,我会收到有关代码的反馈。更不用说把它发送给测试团队了,等了一个星期让他们对它进行一系列的测试,然后不得不被拉出一个不同的用户故事,试图弄清楚我一周以前在想什么。

它们也意味着你可以重构并合理地确定你不仅仅是把所有内容都填满了,有助于让你考虑代码的设计,充当文档和其他各种可爱的东西。但对我来说,TDD的杀手级功能是即时反馈。

答案 1 :(得分:3)

用三个词来说,保存你的测试。

许多优秀的程序员在测试时会进行测试,但他们不会保存测试。他们只需编写一些代码就可以在编写代码时对其进行测试。从“test”作为动词(例如我测试代码)到“test”作为名词(例如,这是对代码的测试。)

TDD还有更多,但这是一个良好的开端。

答案 2 :(得分:2)

TDD意味着让您的测试驱动您的开发过程。起初看起来似乎效率低下,但我会在一秒钟之内完成。

基本上,该过程与上述人员的过程相同:

  1. 编写测试 - 测试您想要的功能(但尚不存在)
  2. 编写最少的代码 - 填写足以让您刚刚编写的测试通过
  3. 重复 - 返回步骤1,直到您拥有所需的所有功能
  4. 这通常意味着编写引用对象的测试,然后编写该对象的定义。然后编写一个在该对象上使用方法的测试,然后编写方法本身。你工作时间很短,从测试到编码都是来回的(短的=向上几秒钟到两边一分钟左右)。

    TDD的理念是您需要100%(理想情况下)测试覆盖率。从逻辑上讲,如果要编写测试,可以选择在实际编写功能之前或之后编写它们。在编码之前执行此操作的优点是:

    • 你实际上测试了你的测试,因为它们应该失败(当你编写它们时)然后传递(当你编写代码时)
    • 您保证始终拥有大量的测试覆盖率
    • 当你去重构时,你知道你有很多测试覆盖率,以确保你不做一些愚蠢的事情(这是我看到的最大优势,因为很多时候你正在处理你已经忘记的旧代码所有细微之处)

    有些人说这有助于他们清楚地定义他们将要做的事情,因此他们可以更快地填写代码。即使需要更长时间,当您回到该代码并稍后重构/更改/优化它时,构建测试覆盖率似乎也是有利的。而且,无论您决定在编码之前还是之后进行测试,我认为我们都同意在某种程度上进行测试(请不要在这里测试宗教辩论)。

答案 3 :(得分:2)

这对你来说似乎有效:

  
      
  • 我完成了一个大脚本,
  •   
  • 评论除我要检查的部分之外的所有内容
  •   
  • 执行脚本
  •   

不是。如果您事先没有设置,那么“您要检查的部分”可能无法正常工作。在运行测试之前确定要评论的内容以及未注释的内容(只需一次!)很难做到并且需要花费大量时间 - 并且可能会给您留下误报结果(您认为您的代码正常运行,但它不是)。正确地取消评估生产代码会带来另一个错误风险。每次你想要检查你的代码时都必须这样做 - 你可能无法检查出错的代码,认为这样做太简单了。

使用TDD - 通过测试驱动设计和单元测试 - 我们避免了所有这些陷阱。我们正在编写微小的测试,所以他们不需要花太多时间来编写,他们只能测试很少的功能。这促使我们大多数人写小功能和小班;那是(好的)设计的一部分;它促进了重用并减少了耦合。并且,作为副作用 - 我不能强调它是副作用,而不是主要的好处 - 我们得到全面的测试覆盖。我们的测试小而快,每天可以运行数百次,所以他们让我们知道我们搞砸了什么。而且因为它们很小而且专注,它们不仅仅告诉我们我们已经搞砸了;他们告诉我们我们搞砸了什么

好的设计:微小的方法,微小的类,最小的耦合;只有我们需要的代码才能满足我们的实际需求;全面的自动化单元测试覆盖效率很高。

答案 4 :(得分:1)

我无法用正确的术语解释它,但我可以告诉你,一般来说,TDD确实允许开发人员专注于任务的ACTUAL要求。它相当于另一种迫使要求非常具体和详细的​​方法。一旦测试完全充实,那么完成测试的任何代码都会完成。期。该任务的开发结束。

这比其他方式更有效还是更低效?在一个完美的世界里,我不这么认为。但我们大多数人并不生活在一个完美的世界里。因此,在我看来,如果能够以100%准确度以某种方式表示要求的唯一人是测试创建者,那么它可以正常工作。程序员不会花时间猜测要做什么,他们不会写出不能发生的条件等等。

我是TDD的支持者,但我不得不承认我从未参加过这样做的组织。

答案 5 :(得分:1)

网上有无数关于TDD的文章。我一直在使用TDD一年,所以我不是专家,但这里是我喜欢TDD的简短摘要:

  • 首先关注您的目标,而不是实施
  • 它使您实现完成任务所需的最小代码,仅此而已。你可以将其重构为更加节奏的东西,但总的来说,你倾向于更密切地遵循YAGNI原则。
  • 最重要的是:你可以无所畏惧地重构你的代码,因为知道你在上次重构过程中没有破坏任何东西(这假设你有一个很好的测试覆盖率,但这是使用TDD的一部分)。这会让你更敏捷。
  • 如果您拥有良好的测试覆盖率,频繁部署到生产环境也会降低危险。

虽然TDD需要一些时间来习惯它,但你会发现它实际上没有传统编码效率低。相反,因为从长远来看,调试代码的时间往往会少得多。

话虽如此,我不是TDD强硬派。在某些情况下,我更喜欢在编写实现后编写单元测试。当我使用新技术时,它比TDD更容易,并且在我实现它之前不知道所期望的结果是什么样的(例如ASP.NET MVC中的ViewResult对象)。

答案 6 :(得分:0)

TDD还可以帮助您获得令人敬畏的测试覆盖率,并且有点迫使您构建结构良好,分离的代码=>良好的可测性。

如果您构建一个100%TDD的系统,您将对所有内容进行测试,这意味着您的系统将更加安全,并且将来实施错误的可能性会更小。

开发需要更长时间,但从长远来看会提供更好的结果。

答案 7 :(得分:0)

您应该编写单元测试:

  • 单元测试可以为自己付出代价,因为它们可以减少错误数量。
  • 代码应该按原样进行测试,测试应该很容易在现在和将来运行,所以评论 - 测试的一切方法都已经完成。
  • 你应该测试一些功能,以防止事情变得太复杂而无法测试。

在编写代码之前或之后是否这样做并不重要。有人说如果你在实施后编写测试,你就会改变你的测试以适应实现,这会降低单元测试的有效性。

答案 8 :(得分:0)

  

我遵循第一种做事方式。

许多其他人也是如此

  

......第二种方式......似乎是一种非常低效的做事方式。

所有新的和不同的东西似乎效率低下。习惯于其他人都错了,你是对的。

你的职业生涯的其余部分将充满这种感觉。每一件新事物似乎效率低下。并且总是效率低下。

  

你能用更简单的方式解释TDD及其优点吗?

TDD效率更高,因为它效率更高。

必须进行测试。您可以先写或最后编写测试。无论哪种方式,你都要写它们。

你可以“评论除我要检查的部分之外的所有内容”,并尝试以缓慢,无效的方式查找错误。它通常是无效的,因为 - 如果没有测试来推动您的开发 - 您可能会编写无用的代码或浪费时间。

或者您可以编写测试并以有效的方式编写通过测试的最少代码