Ruby on rails TDD是否意味着无论多么复杂,我都必须为每种方法编写一个测试?

Ruby on rails TDD是否意味着无论多么复杂,我都必须为每种方法编写一个测试?,ruby-on-rails,tdd,Ruby On Rails,Tdd,假设我有一个用户类,它有一个方法,这个方法够旧了吗 该方法只检查年龄是否超过18岁。看起来很简单 TDD是否意味着我必须为此编写一个测试,即使它很琐碎 class User def is_old_enough? self.age >= 18 end end 如果是,为什么?为此编写测试有什么好处?您只需测试x>=y的工作方式是否与您期望的>=运算符的工作方式相同 因为我看到的最有可能发生的情况如下: 事实证明这个年龄应该是21岁。这是测试没有发现的一个bug,因为在我们编

假设我有一个用户类,它有一个方法,这个方法够旧了吗

该方法只检查年龄是否超过18岁。看起来很简单

TDD是否意味着我必须为此编写一个测试,即使它很琐碎

class User
  def is_old_enough?
    self.age >= 18
  end
end
如果是,为什么?为此编写测试有什么好处?您只需测试x>=y的工作方式是否与您期望的>=运算符的工作方式相同

因为我看到的最有可能发生的情况如下:

事实证明这个年龄应该是21岁。这是测试没有发现的一个bug,因为在我们编写代码时,他们的假设是错误的。然后他们进入并将方法更改为>=21。但是现在测试失败了!所以他们也必须去改变测试。所以测试没有帮助,实际上在他们重构时发出了一个假阳性警报


看起来像这样的简单方法的测试实际上并没有测试任何有用的东西,实际上正在伤害您。

我认为您混淆了测试覆盖率和测试驱动开发。TDD只是一种开发自动化测试的实践,它将验证一些新特性的用例。通常,它一开始会失败,因为您已经中断了功能,或者根本没有实现它。接下来,开发特性,直到测试通过

其想法是,您正处于开发测试的心态,以验证您的重要用例/特性。这并不一定意味着您需要测试简单的功能,如果您认为这些功能已经包含在常规的功能测试中


就覆盖率而言,这实际上取决于作为开发人员(或团队)的您来决定。显然,需要对API的测试进行1对1的覆盖,但您可以选择是否认为实现
足够简单?
。现在看来这似乎是一个简单的实现,但将来可能会有所改变。在选择是否编写测试时,您只需要注意这些类型的决定。不过,更有可能的是,您的用例不会改变,测试也很容易编写。在代码的所有方面都感到自信并没有坏处。

我认为问题更多地与单元测试有关,而不是TDD

简短回答:关注行为

详细回答:好吧,有一个很好的短语:BDD是TDD做得对的,我完全同意。虽然BDD和TDD在很大程度上是“相同”的(请注意,两者并不相等),但BDD为我提供了进行TDD的上下文。你可以在互联网上读到很多关于这方面的文章,所以我不会在这里写文章,但让我说:

  • 在您的示例中,是的,测试是必要的,因为规则 用户年龄足够大是用户实体的一种行为。考试作为一种考试 许多其他事情的安全网还没有到来,这将依赖于此 一条信息,我的测试将记录这种行为 非常好(我实际上倾向于阅读测试,以了解开发人员在编写类时的想法-您可以了解预期内容、类的行为方式、边缘情况等)
  • 我真的看不出这个测试是如何不抓住重构的,因为我会在编写测试时记住数字18、19、25和55(只是一堆非常快速、非常容易键入的断言)

其中非常重要的一点是,单元测试只是您需要的一种技术。如果你的设计不完善,你会发现自己编写了太多没有意义的测试,或者你会让地狱般的测试类做很多事情等等。你需要有非常好的扎实的技能,以便能够以一种只测试类的公共接口(这也包括受保护的方法)的方式来塑造类,从而实际测试整个类。正如前面所说,关注行为是这里的关键。

我认为“测试驱动”意味着测试代码。这并不意味着你必须变得愚蠢。另一方面,有时相对简单的代码可能会有bug。如果有人在一个地方更改了定义,那么测试可能会在另一个地方失败。您必须同时进行阳性和阴性测试(例如,“18分通过,17分不通过”)。如果限制更改为16,您的第二次测试将失败。我总是告诉人们“当你学到新东西时,不要拔掉常识模块为新信息腾出空间”。有了TDD,你不会为方法编写测试,而是为测试编写方法。首先编写一个测试,描述一些期望的但尚未实现的行为。然后编写必要的代码以使测试通过。