Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 在进行TDD时,我为什么要这样做;“刚好够”;为了通过考试?_Unit Testing_Tdd - Fatal编程技术网

Unit testing 在进行TDD时,我为什么要这样做;“刚好够”;为了通过考试?

Unit testing 在进行TDD时,我为什么要这样做;“刚好够”;为了通过考试?,unit-testing,tdd,Unit Testing,Tdd,看看类似于和其他的帖子,似乎做TDD的正确方法是为一个特性编写一个测试,让该特性通过,然后添加另一个测试,并根据需要重构,直到它通过,然后重复 我的问题是:为什么使用这种方法?我完全理解写测试第一的想法,因为它有助于您的设计。但是为什么我不为一个特定的函数创建所有的测试,然后一次性实现该函数,直到所有测试都通过呢?这是一个很好的问题。您需要在编写所有可能的测试和最可能的用户场景之间找到平衡。一个测试是,IMHO,还不够,我通常喜欢编写3或4个测试,它们代表了该特性最常见的用途。我也喜欢写一个最好

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


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

这是一个很好的问题。您需要在编写所有可能的测试和最可能的用户场景之间找到平衡。一个测试是,IMHO,还不够,我通常喜欢编写3或4个测试,它们代表了该特性最常见的用途。我也喜欢写一个最好的测试和一个最坏的测试


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

我认为这源自“YAGNI”(“您不需要它”)(*)的原则,该原则规定类应尽可能简单,没有额外的功能。因此,当您需要一个特性时,您需要为它编写一个测试,然后编写该特性,然后停止。如果您首先编写了许多测试,那么很明显,您只是在猜测您的API在将来的某个时候需要是什么


(*)我通常将其翻译为“你太愚蠢了,不知道将来需要什么”,但这是另一个话题……

我会按照你的建议去做。为特定函数编写多个测试,实现该函数,并确保该函数的所有测试都通过。这可以确保您了解函数的用途和用法,而不必执行它。

这种方法来自极端编程原则,您不需要它。如果您实际编写了一个测试,然后编写了使其通过的代码,然后重复该过程,您通常会发现您编写的代码刚好足以让事情正常工作。你不会发明不需要的新特性。你不能处理根本不存在的案件


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

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


我认为这一想法的一部分是保持简单,保持设计/规划的功能,并且确保你的测试是足够的。

我相信TDD提倡一次编写一个测试,因为它迫使你在开发的每一步都按照做最简单的事情的原则来思考。

我认为它减少了过度设计代码的机会写作


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

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

另一方面,如果一次只执行一个任务,那么每次都会重构现有代码,最终得到的代码可能会尽可能简单,适用于所有场景


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

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

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

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

然而,除此之外,还有复杂性问题。正如人们常说的那样,编程就是管理复杂性——将事物分解成可理解的单元

如果您编写10个测试来覆盖以下情况:param1为null、param2为null、string1为空、int1为负,并且一周中的当前一天是周末,然后去实现它,那么您必须同时处理大量的复杂性。这为引入bug打开了空间,并且很难找出测试失败的原因

另一方面,如果您编写第一个测试来覆盖一个空的string1,您几乎不需要考虑实现。一旦测试通过,您将转到当前日期为周末的情况。看看现有的代码,逻辑应该放在哪里就很明显了。您运行测试,如果第一个测试现在失败了,您知道您在实现每周工作日时破坏了它。我甚至建议您在测试之间提交源代码,这样,如果您破坏了某些东西,您可以始终恢复到通过状态并重试

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

对我来说,这是关于“思想负担”