3

我不确定“先测试”是如何工作的,我想听听关于何时以及为何采用这种方法的争论。

我听说通常建议在编写单行实现之前编写测试和模拟事物。但是,我不禁认为它并不适合所有情况。例如,假设我正在制作一个原型,但我还不确定一切将如何工作。所以我只是开始寻找我认为我需要的每个步骤的示例并将它们放入我的代码中。最后,我证明了我的理论,并没有花那么长时间。这本质上是“我的测试”。这不是单元测试,而是测试(很可能是控制台应用程序)。

这几乎就是我的工作方式。我想我想做什么并尝试去做。如果它有效,那么我最终会回去编写单元测试,以便我可以捕获回归。这与您“应该做的”不同吗?

4

7 回答 7

7

最重要的规则是:先做最危险的事情。

首先进行测试用例隐含地认为编码中最危险的部分是对正在创建的对象的接口和行为的错误沟通和误解。

对于许多项目来说,这很可能是正确的,TDD 在这些情况下非常合适。

然而,在许多项目中并非如此,在这些情况下应用 TDD 是一个糟糕的选择。

如果您的最高风险是可用性,请停止使用单元测试并进行一些 UI 原型设计。

如果你最大的风险是性能,先做一些性能原型,不要担心接口。

这个清单还在继续。

先做有风险的项目有很多好处:

  • 在许多资源被浪费之前,不可避免地注定要失败的项目会提前夭折。

  • 遇到麻烦但可以挽救的项目尽早获得项目管理的关注,因为它可以做一些好事。

  • 当项目失败的风险较低时,您组织的业务方会更高地重视项目;不必要地提前取消的可能性较小。

于 2008-11-26T02:26:35.187 回答
3

“我听说经常建议在编写单行实现之前编写测试和模拟事物......我最终回去编写单元测试......这与你“应该做的”不同吗?”

既然你是从自己的问题的答案开始的,那么你并不是真的在问这个问题,是吗?

人们回答自己的问题有很多原因。有时,这是一种争论的方式。
它允许人们说“我不是在争论,我只是在问为什么这是错误的”。


目标是先测试。这是它的工作原理。

假设我正在制作原型,但我不确定一切将如何工作。

然而,我确实知道一件事。它应该做什么。

  1. 写下它应该做什么的具体例子。具体的、特定的输入和输出。

  2. 这就是测试用例。我先做了。我可以将其正式化为单元测试吗?可能不是。但是,我从一个验收测试用例开始。

现在,我可以将问题分解为多个部分。

  1. 所以我只是开始寻找我认为我需要的每个步骤的例子。

  2. 对于我认为我需要的每个示例,我都会写下步骤中的内容和结果。

  3. 这些是测试用例。我先做了。在许多情况下,我可以将它们形式化为单元测试。

  4. 完成测试后,我会回到每个步骤的示例并将其放入我的代码中。

我做了测试,然后编码。在进行任何编码之前,我没有进行所有测试。我首先进行了测试,但不是以一种疯狂的全测试无代码方式。我以增量测试-一点-代码-一点的方式做到了。但一切都是先测试的。

于 2008-11-26T02:40:53.177 回答
2

这很简单,答案是在原型制作期间。在这个阶段,您对您构建的系统还不够了解,无法正确测试,无论如何,良好的实践表明原型代码应该是一次性代码,因此在这个阶段测试不会给您带来任何真正的好处。但是从原型设计中获得的理解将帮助您,这样您就可以在投入生产后进行有效的测试。

所以是的,如果您在原型之后进行测试,您的方法是正确的

于 2008-11-26T01:42:36.913 回答
1

我认为您不测试尖峰/原型的方法很好。但是有两个想法:

  1. 一旦你完成了你的原型并且你知道你在做什么,要么把它扔掉并重新实现它先测试,或者为你已经编写的代码编写测试。

  2. 当您有更多的单元测试实践时,您可能会发现在测试中创建原型比创建控制台应用程序更快。我不是说创建一个测试和一个单独的类,我的意思是在测试方法中探索 w/code。我已经做过很多次了,我对此非常满意。当我学习新的 API 甚至新语言时,测试给了我最快的反馈周期来尝试实验。然后,一旦代码正常工作,我就可以将其提取到一个单独的方法/类中,成为真实系统的一部分。

于 2008-11-26T03:52:03.610 回答
1

即使你正在编写一个废弃的原型,考虑原型实际上会做什么仍然很有用,并从确认它可以做的测试开始。确保原型可以被测试也将塑造解决方案的方式。

然后,当代码被丢弃时,您仍然有测试。

从原型测试开始我也遇到了麻烦,但是当我设法做到这一点时,我总是很高兴我做到了。

于 2008-11-26T07:58:43.940 回答
0

我发现当我仍在构建代码的“故事”时,首先编写测试并不能很好地工作。当我不确定接口是什么样子时,很难编写测试。我可能会编写存根代码来充实类和接口而不考虑测试。但我试图尽快进行测试。我发现如果我在构建设计时记下要测试的东西会很有帮助,然后当我的设计更加稳固时,我会回到我的笔记并首先进行这些测试。这通常意味着实现和单元测试代码一起增长,两者都不是在另一个之前。

于 2008-11-26T02:39:31.260 回答
0

没有单一的“正确的方法”。但是,我确实认为测试驱动开发 (TDD) 会对您的情况有所帮助。我发现首先编写测试有助于塑造 API 并使代码更简洁。当您首先编写测试时,您首先会考虑如何调用代码(接口,或“这应该做什么”),然后再考虑实现(“我应该怎么做”)。

例如,想象一下创建一个 CRM 模块。您可能会认为首先要做的是吸引花费最多钱的客户。所以,你会写一个测试:

Assert.AreEqual(Customer1, crm.GetMostValuableCustomer(), "最有价值的客户不符合预期");

然后,您可能会遵循以下内容:

Assert.AreEqual(new Customer[] {Customer1, Customer2, Customer3}, crm.GetCustomerByValue(), "GetCustomersByValue() 不符合预期");

所以,关键是你从不同的角度考虑代码(作为消费者,而不是作为生产者)。我相信可以帮助我编写更简洁的代码,并且我不必稍后再返回并创建回归测试。我希望我有一个更好的例子,但希望你能看到在这种方法中工作实际上如何在原型设计阶段帮助你。

于 2008-11-26T02:57:45.093 回答