TDD的要求不明确

时间:2009-11-29 11:04:52

标签: unit-testing tdd

我知道TDD有很多帮助,当你第一次创建测试然后实现这个功能时,我喜欢这种开发方法。这是非常明确和正确的方式。

但是由于我的项目的一些风味,经常会发生这样的事情,当我开始开发一些模块时,我很少知道我想要什么以及它最终会如何看待。这些要求在我开发时出现,当我删除全部或部分旧代码并编写新代码时,可能会有2或3次迭代。

我看到两个问题: 我希望尽快看到结果,了解我的想法是对还是错。单元测试会减慢此过程。因此,在代码完成之后我经常会编写单元测试,这是一个糟糕的模式。 2.如果我第一次编写测试,我不仅要重写代码两次或更多次,还要重写测试。这需要很长时间。

有人可以告诉我在这种情况下如何应用TDD?

提前致谢!

11 个答案:

答案 0 :(得分:12)

  

我希望尽快了解结果,了解我的想法是对还是错。单元测试会减慢这个过程。

我不同意。单元测试和TDD通常可以加速获得结果,因为它们会迫使您专注于结果,而不是实现您可能永远不需要的大量代码。它还允许您在编写代码时运行代码的不同部分,这样您就可以不断查看获得的结果,而不必等到整个程序完成。

答案 1 :(得分:7)

我发现TDD在这种情况下效果特别好;事实上,我会说不清楚和/或不断变化的要求实际上很常见。

我发现TDD的最佳用途是确保您的代码正在按照您的预期执行。当您编写任何代码时,您应该知道您希望它做什么,是否要求是明确的。这里TDD的优势在于,如果需求发生变化,您只需更改一个或多个单元测试以反映更改的需求,然后更新代码,同时确保您不会破坏其他代码(不变) )功能。

我认为使用TDD绊倒很多人的一件事是假设所有测试需要提前编写。我认为使用经验法则更有效的是,当你的所有测试都通过时,你永远不会编写任何实现代码;这只是确保覆盖所有代码,同时确保您检查所有代码是否符合您的要求而不必担心预先编写所有测试。

答案 2 :(得分:5)

恕我直言,你的主要问题是你必须删除一些代码。这是浪费,这是首先要解决的问题。

也许你可以原型化,或利用“尖峰解决方案”来验证需求,然后在需求稳定后,将TDD应用于实际代码。

风险是应用这个并且必须运送原型。

此外,您可以先测试“阳光路径”,然后仅在要求被固定后才实施剩余的错误处理等。然而,实施的第二阶段将不那么激励。

您使用的是哪种开发流程?当你进行迭代时,它听起来很敏捷,但在完全支持迭代的环境中则不然。

答案 3 :(得分:2)

TDD可帮助您表达代码的意图。这意味着编写测试时,您必须说出您对代码的期望。那么你的期望如何实现是次要的(这是实施)。问自己一个问题:“更重要的是,实施或提供的功能是什么?”如果是实现,那么您不必编写测试。如果它是提供的功能,那么首先编写测试将帮助您。

另一个有价值的事情是,通过TDD,您将无法实现不需要的功能。您只编写需要满足意图的代码。这也叫做YAGNI(你不需要它)。

答案 4 :(得分:2)

没有远离它 - 如果你只是通过编写类等等来测量代码所需的时间,那么TDD需要更长的时间。如果你有经验,它会增加约15%,如果你是新手,如果不是更多,它将至少花费60%。

但总的来说,你会更快。为什么呢?

  • 首先编写一个测试,然后指定你想要的东西,只提供它,而不是更多 - 因此节省了编写未使用代码的时间
  • 没有经过测试,您可能会认为结果是如此明显,以至于您所做的事情是正确的 - 如果不是。测试证明你所做的是正确的。
  • 您将从自动化测试中获得比通过手动测试更快的反馈
  • 通过手动测试测试所有内容所需的时间,因为您的应用程序增长迅速增加 - 这意味着您将停止这样做
  • 通过手动测试很容易出错,并且“看到”不通过的东西,如果你一次又一次地运行它们尤其如此
  • (好的)单元测试为您的代码提供了第二个客户端,这通常会突出您可能会错过的设计问题

添加所有这些,如果你从开始到交付进行衡量,TDD的速度要快得多 - 你得到的缺陷就越少,风险就越小,你就能以稳定的速度前进(这使估算更容易)和清单继续。

TDD会让你更快,毫无疑问,但这并不容易,你应该给自己一些学习的空间,如果最初看起来更慢,就不会感到沮丧。

最后,你应该看看BDD的一些技术,以增强你在TDD中所做的工作。从您想要实现的功能开始,然后通过提取故事和场景来深入了解代码。专注于在精简垂直切片中按场景实施解决方案场景。这样做有助于澄清要求。

答案 5 :(得分:2)

对于任何人来说,TDD将会减缓初期开发速度。因此,如果初始开发速度为1-10级,那么使用TDD,如果您精通,则可能会达到8级。

之后的开发那个有趣的点。随着项目变得越来越大,开发效率通常会下降 - 通常会达到相同规模的3。使用TDD,它仍然可以保持在7-8范围内。

查看“技术债务”以获得良好的阅读效果。就我而言,任何没有单元测试的代码都是有效的技术债务。

答案 6 :(得分:1)

使用TDD实际上可以让您更快地编写代码 - 无法为特定场景编写测试可能意味着需求中存在问题。
当您使用TDD时,您应该更快地找到这些有问题的地方,而不是在编写80%的代码之后。

您可以采取一些措施使您的测试更能抵御变化:

  1. 你应该尝试在里面重用代码 你的工厂形式的测试 创建测试的方法 对象以及验证方法 检查测试结果。这个 如果一些主要行为发生变化 在您的代码中出现较少的代码 代码可以在测试中更改。

  2. 使用IoC容器而不是传递 主要类的参数 - 再次如果方法签名 您无需更改的更改 所有的测试。

  3. 使您的单元测试简短且隔离 - 每个测试应仅检查代码的一个方面,并使用模拟/隔离框架使测试独立于外部对象。

  4. 仅测试和编写所需功能(YAGNI)的代码。试着问问自己,我的客户将从我正在撰写的代码中获得什么价值。不要创建过于复杂的体系结构,而是在您重新编写代码时逐个创建所需的功能。

答案 7 :(得分:0)

这是一篇博文,我发现在一个非常迭代的设计过程中解释TDD的使用是有效的:http://blog.extracheese.org/2009/11/how_i_started_tdd.html

答案 8 :(得分:0)

Joshua Block在“Coders at work”一书中评论了类似的内容。他的建议是编写如何使用API​​的示例(关于页面的长度)。然后仔细考虑示例和API并重构API。然后编写规范和单元测试。但是,请准备重构API并在实现API时重写规范。

答案 9 :(得分:0)

当我处理不明确的要求时,我知道我的代码需要更改。进行可靠的测试有助于我更轻松地更改代码。练习TDD可以帮助我编写可靠的测试,这就是我这样做的原因。

尽管TDD主要是一种设计技术,但它在您的情况下有一个很大的好处:它鼓励程序员考虑细节和具体方案。当我这样做时,我注意到我发现差距或误解或要求不够清晰。试图编写测试的行为迫使我处理要求缺乏明确性,而不是试图在地毯下扫除这些困难。

因此,当我的要求不清楚时,我会练习TDD,因为它可以帮助我确定我需要解决的具体需求问题,但也因为它鼓励我编写我觉得更容易改变的代码,因为我更了解什么我需要建立。

答案 10 :(得分:-1)

在这个早期的原型阶段,我发现编写可测试代码就足够了。也就是说,当您编写代码时,请考虑如何使测试成为可能,但是现在,请关注代码本身而不是测试。

当您提交某些内容时,您应该进行测试。