YAGNI在编写测试时是否也适用?

时间:2009-06-03 15:44:57

标签: unit-testing language-agnostic tdd yagni

当我编写代码时,我只会根据需要编写我需要的函数。

这种方法是否也适用于编写测试?

我是否应该提前为每个用例编写一个测试,我认为只是为了安全起见,或者我应该只为用例编写测试?

11 个答案:

答案 0 :(得分:13)

我认为在编写方法时,您应该测试预期和潜在的错误路径。这并不意味着您应该扩展您的设计以涵盖所有可能的用途 - 在需要时留下它,但您应该确保您的测试已经定义了面对无效参数或其他条件时的预期行为。

根据我的理解,YAGNI意味着您不应该开发尚不需要的功能。从这个意义上讲,您不应该编写一个测试来驱动您开发不需要的代码。不过,我怀疑这不是你要问的问题。

在这种情况下,我会更关心你是否应该编写涵盖意外用途的测试 - 例如,由于传递null或超出范围参数而导致的错误 - 或者重复只对数据有所不同的测试,不是功能。在前一种情况下,如上所述,我会说是的。您的测试将记录方法在遇到错误时的预期行为。这对使用您方法的人来说是重要的信息。

在后一种情况下,我不太能给你一个确定的答案。你当然希望你的测试保持干燥 - 即使它有不同的数据,也不要写一个只重复另一个测试的测试。或者,您可能不会发现潜在的设计问题,除非您处理数据的边缘情况。一个简单的例子是计算两个整数之和的方法:如果将maxint作为两个参数传递,会发生什么?如果您只有一个测试,那么您可能会错过这种行为。显然,这与前一点有关。只有你可以确定何时真正需要测试。

答案 1 :(得分:9)

是的,YAGNI绝对适用于编写测试。

举个例子,我不会编写测试来检查任何属性。我假设属性以某种方式工作,直到我找到一个与常规不同的东西,我将不会对它们进行测试。

您应该始终考虑编写任何测试的有效性。如果在编写测试时没有明显的好处,那么我会建议你不要。然而,这显然非常主观,因为您可能认为不值得其他人认为非常值得努力。

另外,我会编写测试来验证输入吗?绝对。但是,我会到点。假设你有一个带有3个int整数参数的函数,它返回一个double。你要围绕这个功能编写多少个测试。我会在这里使用YAGNI来确定哪些测试能够让你获得良好的 ROI ,哪些测试无用。

答案 2 :(得分:4)

根据需要编写测试。测试是代码。在前面编写一堆(最初失败的)测试会破坏TDD的红色/修复/绿色循环,并且更难以识别有效的故障与未编写的代码。

答案 3 :(得分:4)

您应该为在此开发阶段实施的用例编写测试。

这带来了以下好处:

  1. 您的测试有助于定义此阶段的功能。
  2. 您知道当您完成此阶段,因为所有测试都通过了。

答案 4 :(得分:3)

理想情况下,您应该编写涵盖所有代码的测试。否则,其余的测试将失去价值,最终您将重复调试该段代码。

所以,不。 YAGNI不包括测试:)

答案 5 :(得分:3)

你可能会在这里得到一些变化,但一般来说,编写测试(对我而言)的目的是确保所有代码按预期运行,没有副作用,以可预测的方式并且没有缺陷。那么,在我看来,你所讨论的方法只是在用例发生时对它们进行测试,这样你就没有真正的好处,事实上可能会造成伤害。

如果您忽略的被测单元的特定用例会导致最终软件出现严重缺陷,该怎么办?开发测试所花费的时间是否超出了虚假的安全感,在这种情况下为您带来了什么?

(对于记录,这是我使用代码覆盖来“测量”测试质量的问题之一 - 这是一个测量,如果低,可能表明你没有测试足够,但如果高,不应该用来假设你是坚如磐石的。测试常见案例,测试边缘案例,然后考虑单元的所有ifs,ands和buts,并测试它们。)

温和更新

我应该注意到,我的观点可能与许多观点不同。我经常发现我正在编写库式代码,即可以在多个项目中重用的代码,用于多个不同的客户端。因此,我一般不可能肯定地说某些用例根本不会发生。我能做的最好的是要么没有预期的文件(因此可能需要在之后更新测试),或者 - 这是我的偏好:) - 只是编写测试。我经常发现选项#2在日常生活中更适合居住,仅仅因为当我在新的应用程序Y中重用组件X时我更有信心。在我看来,自信是自动化测试的所有关于。

答案 6 :(得分:3)

编写测试用例当然没有意义,你根本不确定是否会实现 - 对任何人来说都应该是显而易见的。

对于您知道将要实现的用例,测试用例会收益递减,即当您可以用一半的工作覆盖所有重要和关键路径时,尝试覆盖每个可能的模糊角落案例并不是一个有用的目标 - 当然,假设忽视一个很少发生的错误的成本是可以忍受的;在编写航空电子软件时,我肯定不会满足于任何低于100%的代码和分支覆盖率。

答案 7 :(得分:2)

你当然不应该为你还没有实现的功能编写测试用例。只应针对您即将投入的现有功能或功能编写测试。

但是,用例与功能不同。您只需要测试已识别的有效用例,但是可能会发生许多其他事情,并且您希望确保这些输入得到合理的响应(这可能是错误消息)

显然,你不会得到所有可能的用例;如果可以的话,就没有必要担心计算机安全问题了。你应该至少得到更合理的问题,并且当出现问题时你应该将它们添加到用例中进行测试。

答案 8 :(得分:1)

我认为这里的答案是,因为它在很多地方,取决于它。如果一个函数提出的合同表明它有X,并且我看到它有相关的单元测试等,我倾向于认为它是一个经过良好测试的单元并且如此使用它,即使我不这样做在其他地方使用它。如果该特定使用模式未经测试,那么我可能会遇到令人困惑或难以追踪的错误。出于这个原因,我认为测试应该涵盖一个单元的所有(或大多数)已定义的记录行为。

如果您选择以递增方式进行更多测试,我可能会在文档注释中添加该函数“仅针对[某些类型的输入进行测试],其他输入的结果未定义”。

答案 9 :(得分:0)

我经常发现自己编写测试,TDD,用于我不希望调用正常程序流的情况。 “伪造它直到你制造它”的方法让我开始,一般来说,使用空输入 - 足以让人想到函数调用应该是什么样的,它的参数将具有什么类型以及它将具有什么类型返回。要清楚,我不会在测试中向函数发送null;我将初始化一个类型变量来保存null值;当Eclipse的Quick Fix为我创建函数时,它已经有了正确的类型。但是我不希望程序正常地向函数发送空值并不罕见。所以,可以说,我正在编写一个我认可的测试。但是,如果我从价值观开始,有时它太大了。我正在设计API并从一开始就推动其真正的实现。所以,通过开始慢速和伪造它直到我做它,有时我会为我不希望在生产代码中看到的情况编写测试。

答案 10 :(得分:0)

如果您使用的是TDD或XP风格,您将不会“提前”写任何内容,因为您说,您将在任何特定时刻处理非常精确的功能,所以你'我将编写所有必要的测试,以确保功能可以按照您的意图运行。

测试代码与“代码”本身类似,您不会为应用程序的每个用例提前编写代码,那么为什么要提前编写测试代码?