5

在阅读了由测试指导的面向对象软件的增长后,我了解到了测试隔离和测试脆弱性。每个测试都应该非常特定于一段代码或功能的想法,并且测试的代码覆盖重叠应该保持在最低限度。隐含的理想是代码中的每次更改都应导致仅破坏一个测试。避免花费时间通过多个损坏的测试来确认一个更改是原因以及它是否已通过测试修改得到修复。

现在这对于单元测试来说似乎很容易,它们本质上是非常孤立的。然而,当集成测试呈现时,似乎很难避免多个测试执行相同的代码路径,尤其是在单元测试之外运行时。

所以我的问题是,在进行集成测试时应该模拟哪些依赖项?任何事情都应该被嘲笑吗?是否应该测试单个执行路径,并且模拟与该代码路径不直接相关的所有副作用?

我在玩成对集成测试的想法。测试两个对象之间的一种关系,并模拟其他一切。那么这些对象中的任何一个的更改都应该对其他集成测试的影响最小,除了通过成对形成完整的端到端测试链之外。

感谢您提供任何信息..

编辑:为了澄清,我基本上是在问“如何在正常的开发过程中避免大量失败的集成测试?”。我认为这是通过使用模拟来实现的,以及为什么我询问要模拟什么。

更新:我发现 JBRainsberger 关于集成测试的一个非常有趣的讨论,我认为它很好地回答了这个问题,虽然可能有点争议。标题是“Integration Tests are a Scam”,所以你可以猜到,他根本不提倡 Integration Tests(端到端类型测试)。争论是集成测试总是远远低于彻底测试可能的交互所需的量(由于组合爆炸),并且可能给出错误的信心。相反,他推荐了他所谓的协作测试和合同测试。这是一个 90 分钟的演讲,不幸的是,白板不是很清楚,也没有代码示例,所以我还在摸索。当我有明确的解释时,我会在这里写!除非别人打败我。。

这是合同测试的简短摘要。听起来像按合同设计类型断言,我相信可以/将在 C++ 中的非虚拟接口模式中实现。

http://thecodewhisperer.tumblr.com/post/1325859246/in-brief-contract-tests

集成测试是一个骗局视频谈话: http: //www.infoq.com/presentations/integration-tests-scam

概括:

集成测试是一个骗局。您可能正在编写需要彻底测试的 2-5% 的集成测试。您可能在各处重复单元测试。您的集成测试可能会到处重复。当集成测试失败时,谁知道出了什么问题?学习解决问题的两管齐下的攻击:协作测试和合同测试。

4

4 回答 4

2

对于集成测试,我倾向于模拟服务而不是表示,例如使用mirage而不是 3rd 方 REST API 和Dumpster而不是真正的 SMTP 服务器。

这意味着您的代码的所有层都经过测试,但没有第 3 方经过测试,因此您可以自由重构而不必担心测试会失败。

于 2013-07-26T16:06:26.967 回答
2

对于集成测试,您应该模拟最少数量的依赖项以使测试正常工作,但不能少:-)

由于系统中组件的集成显然是您在集成测试期间要测试的内容,因此您应该尽可能使用真实的实现。但是,您显然想要模拟一些组件,因为您不希望集成测试开始向您的用户发送邮件。当你不模拟这些依赖时,你显然模拟得太少了。

这并不意味着您不应该允许集成测试发送邮件,但至少您希望将邮件组件替换为仅将邮件发送到某个内部测试邮箱的组件。

于 2013-07-26T11:14:39.213 回答
1

单元测试应该有模拟对象,但集成测试应该很少有模拟(否则正在集成什么?)我认为做成对模拟有点过头了;这将导致测试的爆炸式增长,每个测试都可能需要很长时间以及大量的复制和粘贴代码,如果需求发生变化或以后添加新功能,这将是一个痛苦的改变。

我认为在集成测试中没有任何模拟很好。您应该在单元测试中模拟所有内容,以了解每个单独的单元在隔离时按预期工作。集成测试测试所有东西都连接在一起。

于 2013-07-26T15:23:05.423 回答
0

合同/合作者测试模式的讨论(由 JB Rainsberger 在上述问题中提到的“集成测试是一个骗局”中描述)。关于这里的问题 - 我将他的谈话解释为当您拥有服务端和客户端的代码时,您根本不需要任何集成测试。相反,您应该能够依赖实现合同的模拟。

该演讲是对模式的高级描述的一个很好的参考,但没有详细说明(至少对我而言)如何定义或引用协作者的合同。

需要Contract/Collaborator模式的一个常见示例是在 API 的服务器/客户端之间(您拥有两者的代码)。这是我实现它的方式:

定义合约:

首先定义 API Schema,如果你的 API 使用 JSON,你可以考虑JSONSchema。架构定义可以被认为是 API 的“合约”。(附带说明一下,如果您打算这样做,请确保您了解RAML或 Swagger,因为它们本质上使编写 JSONSchema API 变得更加容易)

创建实现合同的固定装置:

  • 在服务器端,模拟客户端请求以允许对请求/响应进行单元测试。为此,您将创建客户端请求装置(又名模拟)。定义 API 后,根据 JSONSchema 验证固定装置以确保它们符合要求。有许多模式验证器——我目前使用 AJV (Javascript) 和 jsonschema (Python),但大多数语言都应该有一个实现。

  • 在客户端,您可能会模拟服务器响应以允许对请求进行单元测试。遵循与服务器相同的模式,通过 JSONSchema 验证请求和响应装置。

如果客户端和服务器都根据合同验证他们的固定装置,那么每当 API 合同发生变化时,双方过时的实现都将无法通过 JSONSchema 验证,您将知道是时候更新固定装置以及可能的代码了依赖于那些固定装置。

于 2016-05-27T15:05:00.810 回答