我应该写一个已通过的测试吗?

时间:2014-03-09 19:17:55

标签: unit-testing tdd

我在谈论叔叔鲍勃的TDD规则:

  1. 除非要通过失败的单元测试,否则不允许编写任何生产代码。
  2. 您不得再编写任何单元测试,而不是足以使其失败;编译失败就是失败。
  3. 您不能再编写足以通过一次失败的单元测试的生产代码。
  4. 我的问题是当您希望创建一个可以生成多于1​​个结果的特征时会发生什么,并且在第一次迭代时您实现的代码可以满足每个场景?
    我写了一次这样的代码,因为这是我首先想到的唯一解决方案。

    我说我没有违反这3条规则中的任何一条。

    1. 我写了一个最不可能的条件失败的测试。
    2. 然后我使用足够的代码实现了该功能以通过测试(这是我提出的唯一解决方案;所以我说我可以编写的代码最少)。
    3. 然后我写了下一个测试,发现它已经过去了。
    4. 现在规则怎么样?
      即使该功能是 soooper 重要功能,我也不被允许编写此测试吗?或者我应该回滚并重新开始?

      我还要提到这个方法不能根据输入的结果或数据进行重构。现在我能想到的例子情况有点愚蠢但请跟我说。看看这个例子:
      我想创建一个添加数字的方法,这几乎是我所能做的。白色是一个失败的测试:

      public function it_can_add_numbers()
      {
          $this->add(2, 3)->shouldReturn(5);
      }
      

      然后通过:

      public function add($numberOne, $numberTwo)
      {
          return $numberOne + $numberTwo;
      }
      

      现在有人可能会争辩说我应该在第一次迭代中返回5,因为这足以通过测试并引入回归,但这不是一个实际问题,所以请耐心等待,并假设这是唯一的人们可以想到的解决方案 现在我的公司希望我确保他们能够添加12和13,因为这些是一些内部神奇的数字,我们将花费很多时间。我继续写另一个测试,因为这是我应该验证一个功能的方式。

      public function it_can_add_twelve_and_thirteen()
      {
          $this->add(12, 13)->shouldReturn(25);
      }
      

      结果证明测试已经过去了 此时,我可以选择不编写测试,但如果稍后有人在实际代码中进行更改并使其成为

      public function add($numberOne, $numberTwo)
      {
          return 5;
      }
      

      测试仍然会通过,但功能不存在。

      那么当您在进行改进之前无法立即考虑在第一次迭代中引入可能的缺陷时,那些情况又如何呢?我应该把它留在这里,等待有人过来搞砸了吗?我应该把这个案子留给回归测试吗?

4 个答案:

答案 0 :(得分:3)

在写完测试之后,要遵守叔叔鲍勃规则中的规则3:

public function it_can_add_numbers()
{
    $this->add(2, 3)->shouldReturn(5);
}

正确的代码为:

public function add($numberOne, $numberTwo)
{
    return 5;
}

现在,当您添加第二个测试时,失败,这将使您更改代码以符合两个测试,然后将其重构为DRY,从而导致:

public function add($numberOne, $numberTwo)
{
    return $numberOne + $numberTwo;
}

我不会说它是编码的“唯一真正的方式”,@ Oli和@Leo有一个观点,你不应该像程序员那样停止思考,因为你是TDDing,但上面的过程就是一个例子遵循您在TDD中陈述的3条规则......

答案 1 :(得分:2)

如果你写了一个通过测试,你就没有做TDD。

这并不是说测试没有价值,但它非常清楚地表明你的新测试不是“驾驶设计”(或“驾驶开发”,“其他”DD)。您可能需要新的测试用于回归或满足管理或提出一些代码覆盖率指标,但您不需要它来推动您的设计或开发。

你确实违反了鲍勃叔叔的第三条规则,因为你写的逻辑比你通过测试所需的逻辑要多。

违反规则是可以的;打破规则并说你没有违反规则是不行的。如果你想像叔叔鲍勃所定义的那样严格遵守TDD,你需要遵循他的规则。

答案 2 :(得分:0)

如果该功能非常简单,就像添加示例一样,我不会担心只用一个测试来实现它。在更复杂的实际情况中,一次实现整个解决方案可能会使您的代码结构不佳,因为您没有机会进化设计并重构代码。 TDD是一种设计技术,可以帮助您编写更好的代码,并且需要您不断思考,而不仅仅是遵循死记硬背的规则。

答案 3 :(得分:0)

TDD是一种最佳实践,而非宗教。如果你的案例是微不足道/明显的,那就写下正确的代码,而不是做一些人工无用的重构

相关问题