4

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

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

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

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

因此,任何关于在哪里可以了解更多关于其中一些方法的资源都会很好。我不想因为我不了解他们做事的方式而放弃一个很好的学习机会。我也想停止关注这些方法的负面影响,看看好处在哪里。

4

2 回答 2

3

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

例如,请参见此处的堆栈示例,该示例具有通用设置(将内容添加到堆栈),然后是一堆独立的测试,每个测试都检查一件事。这里还有另一个例子,这次没有一个测试 (@Test) 修改公共夹具 (@Before),但每个测试都专注于检查应该发生的一件独立的事情。如果测试非常集中,那么应该可以更改生产代码以使任何单个测试失败,而所有其他测试都通过(我最近在Unit Test Focus Isolation中写过)。

主要思想是让每个测试检查一个特性/行为,以便在测试失败时更容易找出失败的原因。有关更多示例并了解该风格,请参阅此 TDD 教程。

我不担心多次执行相同的代码路径,运行一个测试需要一毫秒(如果运行所有单元测试需要几秒钟以上,测试可能太大了)。从您的解释来看,如果每个模拟都有一个测试是系统的,我更担心测试可能与实现过于紧密地耦合,而不是功能。测试的名称将很好地表明测试的结构或脆弱程度——它是否描述了一个特性或该特性是如何实现的。

关于 mocking,一本好书是《Growing Object-Oriented Software Guided by Tests》。由于您已经提到的原因,不应模拟第 3 方 API(您不拥有且无法修改的 API),但应在其上创建一个抽象,以更好地满足使用它的系统的需求并工作你想要的方式。该抽象需要与第 3 方 API 进行集成测试,但在所有使用该抽象的测试中,您都可以模拟它。

于 2012-08-06T22:33:22.583 回答
1

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

  1. 语言 - BDD 的租户之一是,您使用的语言会通过迫使您以最终用户的语言说话来影响您的想法,最终您将编写与以程序员为中心编写测试不同的测试
  2. 测试锁定代码 - BDD 将代码锁定在适当的级别。测试中常见的一个问题是您编写了大量测试,这使您的代码库更加脆弱,因为当您更改代码时,您也必须更改大量测试。BDD 强制您锁定代码的行为,而不是代码的实现。这样,当测试中断时,它更有可能是有意义的。

值得注意的是,您不必使用 Cucumber 测试风格来实现这些影响,并且使用它确实会增加额外的开销层。但很少有程序员在使用传统 xUnit 工具 (TDD) 时成功地保持 BDD 思维方式。

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

最后,这是 Dan North博客的链接——他开始了这一切。

于 2012-08-07T02:52:35.570 回答