代码之家  ›  专栏  ›  技术社区  ›  ryeguy

做TDD时,我为什么要做“就够了” 让考试通过?

  •  14
  • ryeguy  · 技术社区  · 14 年前

    看看像这样的帖子 this 对于其他的,TDD的正确方法似乎是为一个特性编写一个测试,只让该特性通过,然后添加另一个测试并根据需要重构,直到它通过,然后重复。

    我的问题是:为什么使用这种方法?我完全理解写测试第一的想法,因为它有助于你的设计。但是为什么我不能为一个特定的函数创建所有的测试,然后一次实现这个函数,直到所有的测试都通过?

    12 回复  |  直到 14 年前
        1
  •  11
  •   Mike Two    14 年前

    这种方法来自极限编程原理,你不需要它。如果你真的写了一个测试,然后写了一段代码让它通过,然后重复这个过程,你通常会发现你写的足够让事情正常进行。你不会发明不需要的新特性。你不能处理根本不存在的案子。

    尝试一个实验。写出你认为你需要的测试清单。把它放一边。然后采用一次一个测试的方法。看看这些清单是否不同,为什么。当我这样做的时候,我几乎总是以更少的测试结束。我几乎总是发现,我发明了一个案例,我不需要,如果我做所有的测试第一的方式。

        2
  •  4
  •   Carl Manaster    14 年前

    对我来说,这是关于“思想负担”的问题。如果我一下子就要担心所有可能的行为,我的大脑就会紧张。如果我一次一个地接近他们,我就能全神贯注地解决眼前的问题。

        3
  •  3
  •   James Curran    14 年前

    我相信这源于“YAGNI”(“You're't Gonna Need It”)(*)的原则,它指出类应该尽可能简单,没有额外的特性。因此,当您需要一个特性时,您需要为它编写一个测试,然后编写特性,然后停止。如果您首先编写了大量的测试,那么很明显,您只是在猜测您的API在将来的某个时候需要是什么。

    (*)我通常把它翻译成“你太蠢了,不知道将来需要什么”,但那是另一个话题。。。。。。

        4
  •  3
  •   eglasius    14 年前

    在查看不同的使用场景时,添加不必要的代码更容易。

        5
  •  2
  •   Jay    14 年前

    Dan North提出,不存在测试驱动的设计,因为设计并不是真正由测试驱动的——这些单元测试只有在实现了功能之后才成为测试,但在设计阶段,您实际上是在通过示例进行设计。

    这是有意义的——您的测试正在设置一系列样本数据和被测系统将要运行的条件,您将基于这些示例场景进行设计。

    其他一些答案表明,这是基于雅格尼。这在一定程度上是正确的。

    不过,除此之外,还有复杂性问题。正如人们常说的,编程是关于管理复杂性的——将事物分解成可理解的单元。

    另一方面,如果您编写第一个测试来覆盖一个空的string1,那么您几乎不必考虑实现。一旦测试通过,您就可以进入当前为周末的情况。您查看现有的代码,就会发现逻辑应该放在哪里。你运行测试,如果第一个测试现在失败了,你知道你在实现一周中的某一天时破坏了它。我甚至建议您在两个测试之间提交源代码,这样,如果您破坏了某些东西,您就可以始终恢复到正在通过的状态并重试。

    一次只做一点,然后验证它是否有效,这大大减少了引入缺陷的空间,而且当您的测试在实现后失败时,您更改的代码非常少,因此很容易识别缺陷并纠正它,因为您知道现有的代码已经正常工作了。

        6
  •  1
  •   funkymushroom    14 年前

    编写许多测试可以帮助您预测和理解功能的潜在用途。

        7
  •  1
  •   ChrisH    14 年前

    最简单的办法

        8
  •  1
  •   SBUJOLD    14 年前

    我想你发的文章正是答案。如果您先编写所有的测试,然后再编写所有的场景,那么您可能会编写一次处理所有这些场景的代码,并且大多数情况下,您可能会得到处理所有这些场景相当复杂的代码。

    另一方面,如果一次只执行一个,那么每次都会重构现有代码,最终得到的代码可能与所有场景一样简单。

    就像你在问题中给出的链接一样,如果他们先编写所有的测试,我很确定他们不会以一个简单的if/else语句结束,而可能是一段相当复杂的递归代码。

        9
  •  1
  •   CB Bailey    14 年前

    这个原则背后的原因很简单。坚持到底有多实际是另一个问题。

    如果您编写下一个测试来“赶上”生产代码,那么您刚刚编写了一个没有失败的测试。该测试可以称为“TestNextFeature”,但也可以 return true

    TDD就是要确保所有的代码——生产和测试——都经过测试,所有那些讨厌的“但我肯定我写对了”的bug不会进入代码。

        10
  •  0
  •   Bernard    14 年前

    我会照你的建议做。为一个特定函数编写几个测试,实现该函数,并确保该函数的所有测试都通过。这可以确保您从函数的实现中分别了解函数的用途和用法。

        11
  •  0
  •   Gavin H    14 年前

    如果您需要在实现方面比单元测试做更多的工作,那么单元测试可能不够全面。

        12
  •  0
  •   Benjamin Wootton    14 年前

    上面有很多很好的答案-雅格尼是第一个跳进脑海的答案。

    不过,“让测试通过”准则的另一个重要内容是,TDD实际上是一个三阶段的过程:

    红色>绿色>重构

    很难养成这个习惯,但要坚持下去,因为一旦你进入这个周期,这是一种奇怪的令人满意的工作方式。