使用何时和何时和TDD学习单元测试

时间:2012-08-06 21:59:37

标签: unit-testing tdd bdd

我新工作的测试与之前遇到的测试完全不同。

当他们编写单元测试时(大概是在代码之前),他们创建了一个以“When”开头的类。该名称描述了运行测试的场景(夹具)。他们将通过代码为每个分支创建子类。该类中的所有测试都以“should”开头,并且在运行后测试代码的不同方面。因此,他们将有一种方法来验证每个模拟(DOC)是否被正确调用以及检查返回值(如果适用)。我对这种方法有点困惑,因为它意味着每次测试都运行完全相同的执行代码,这看起来很浪费。我想知道是否有类似的技术,他们可能已适应。解释风格及其应该如何实施的链接将是很棒的。我听起来类似于我见过的一些BDD方法。

我还注意到他们已经将重复调用“执行”SUT移动到设置方法中。当它们期望异常时会导致问题,因为它们不能使用内置工具来执行检查(Python unittest的assertRaises)。这也意味着将返回值存储为测试类的支持字段。他们还必须存储许多模拟作为支持领域。在类层次结构中,很难分辨每个模拟的配置。

他们也测试代码有点不同。它真正归结为他们认为的集成测试。他们嘲笑任何窃取背景的东西远离被测试的功能。这可能意味着同一类中的私有方法。我一直限制模拟可能影响测试结果的资源,例如数据库,文件系统或日期。我可以看到这种方法的一些价值。但是,现在使用它的方式,我可以看到它导致脆弱的测试(测试随着每次代码更改而中断)。我担心,因为没有集成测试,在这种情况下,您可能会错误地使用第三方API,但您的单元测试仍然会通过。我想更多地了解这种方法。

所以,任何关于在哪里学习更多关于这些方法的资源都会很好。我不愿意放弃一个很好的学习机会,因为我不了解他们做事的方式。我还想停止关注这些方法的负面影响,看看它带来的好处。

2 个答案:

答案 0 :(得分:3)

如果我理解第一段中的解释,那与我经常做的非常相似。 (取决于测试框架是否易于使用。许多模拟框架也不支持它,但像Mockito这样的间谍框架做得更好。)

例如,请参阅具有通用设置的stack example here(向堆栈添加内容),然后查看一系列独立测试,每个测试都检查一件事。 Here's still another example,这次没有任何测试(@Test)修改公共夹具(@Before),但是每个测试都专注于检查一个应该发生的独立事物。如果测试非常集中,那么应该可以更改生产代码,以便在所有其他测试通过时使任何单个测试失败(我最近在Unit Test Focus Isolation中写到了这一点。)

主要思想是让每个测试都检查一个功能/行为,这样当测试失败时,find out why it failed就更容易了。有关更多示例和了解该样式,请参阅this TDD tutorial

我并不担心多次执行相同的代码路径,当运行一次测试需要一毫秒时(如果需要more than a couple of seconds to run all unit tests,则测试可能太大)。根据你的解释,我更担心测试可能与实现过于紧密耦合,而不是功能,如果它是系统的,每个模拟都有一个测试。测试的名称可以很好地指示测试结构良好或多么脆弱 - 它是描述功能还是如何实现该功能。

关于嘲笑,一本好书要读Growing Object-Oriented Software Guided by Tests。你不应该模仿第三方API(你不拥有和不能修改的API),因为你已经提到的原因,但是应该创建一个抽象,它更适合使用它的系统的需要并且工作你想要的方式。这种抽象需要与第三方API进行集成测试,但在所有测试中使用抽象,你可以嘲笑它。

答案 1 :(得分:1)

首先,您使用的模式基于Cucumber - 这是link。风格来自BDD(行为驱动开发)方法。它比传统的TDD有两个优点:

  1. 语言 - BDD的一个租户是你使用的语言通过强迫你用最终用户的语言来影响你的想法,你最终会编写不同的测试,而不是从焦点编写测试时程序员
  2. 测试锁定代码 - BDD将代码锁定在适当的级别。测试中常见的一个问题是您编写了大量测试,这使得您的代码库更加脆弱,因为当您更改代码时,您也必须更改大量测试。 BDD强制您锁定代码的行为,而不是代码的实现。这样,当测试中断时,它更有可能是有意义的。
  3. 值得注意的是,您不必使用Cucumber样式的测试来实现这些影响,并且使用它会增加额外的开销层。但是,在使用传统的xUnit工具(TDD)时,很少有程序员能够成功地保持BDD的思维模式。

    听起来你还有一些场景,你想说'当我这样做,然后验证'。因为当前的BDD xUnit框架只允许您验证基元(字符串,整数,双精度,布尔值......),这通常会导致大量的单个测试(每个Assert一个)。可以使用Golden Master范例测试工具(例如ApprovalTests)进行更复杂的验证。这是video example

    最后,这里是Dan North的blog的链接 - 他开始了这一切。