彩票走势图

单元测试C/C++代码:何时Mock?

原创|行业资讯|编辑:郑恭琳|2020-12-14 13:48:49.957|阅读 644 次

概述:单元测试就是测试单独的单元。在本文中,我们将进行7次模拟,包括一些有用的问题,以便您可以指导自己完成C和单元测试。

# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>

相关链接:

单元测试就是测试单独的单元。在本文中,我们将进行7次模拟,包括一些有用的问题,以便您可以指导自己完成C和单元测试。

我们需要多少单元测试隔离?在为CC++开发单元测试时,这是一个反复出现的重要问题,经常被争论。我在这里不是在谈论与开发者的隔离,而是坐在开放空间中坐在我们旁边,敲打他耳机的音乐节奏(顺便说一句,当我们想创造出色的质量代码时,这也很重要)。我说的是将经过测试的代码与其周围环境(即所谓的协作环境)隔离开来。

在继续之前,让我先澄清一件事:在讨论CC++语言的存根和模拟时,由于语言层在复杂性,功能和期望方面的差异,通常在CC++之间划清界限。关于典型的模拟框架,使用Parasoft C/C++test时,情况略有不同,因为两种语言都可以使用大多数框架功能。因此,在讨论该主题时,我将给出一个CC++单元测试示例,并且除非我专门将某项标记为仅受CC++支持,否则您应始终假定这两种语言均提供了特定功能。


隔离还是不隔离?

一方面,常识要求除非有充分的理由,否则我们不应该孤立。最后,测试真正的协作者只会增加我们对代码库的渗透。为什么我们要放弃一些额外的代码覆盖范围以及发现错误的可能性?好吧,看来有一些很好的理由——我们将很快进行讨论。

另一方面,一个正统的单元测试人员会认为单元测试是对孤立的单元进行测试,并且应该保持原样。与真正的合作者进行测试是集成阶段的领域。一个众所周知的事实是,通过将真正的环境纳入测试范围,我们可以使测试噪音更大。依赖真实环境的测试不仅会对被测代码中的更改做出反应,而且还会对相关组件中的更改做出反应。嘈杂的测试使维护过程更加昂贵,并且会分散注意力。从长远来看,这种分散注意力通常成为放弃单元测试实践的主要原因。

那么隔离测试代码的策略是什么?鉴于上述情况,很难制定一个好的规则来确定需要mock哪些环境以提供对测试代码的适当隔离。从测试效率和有效性的角度来看,“尽可能地隔离”和“尽可能避免单元测试隔离”这两种方法各有利弊。


3个简单的Mock原因

这是一些更明显的情况:

1.合作者尚未实施或仍在开发中

这很简单。我们别无选择,我们需要一个mock实现。下图说明了这种典型的单元测试环境(SUT——被测系统,DOC——依赖组件/环境):


2.硬件独立性

对于编写桌面应用程序的开发人员来说,这类问题似乎遥不可及,但对于嵌入式开发人员而言,单元测试的硬件独立性是一个重要方面,无需硬件即可实现高水平的测试自动化和执行。一个很好的例子是被测单元与GPS硬件交互,期望提供一定的定位坐标序列来计算速度。尽管我们建议您多做些运动,这是一个好主意,但我无法想象测试人员会在设备上跑来跑去以模拟运动,只是为了生成所需的测试输入,而无论何时需要进行单元测试。为此,该示例说明了如果在开发过程中无法实现硬件独立性,则设备的开发生命周期将进行GPS测试多晚。


3.故障注入

故意注入错误是测试中的常见情况。例如,这可用于测试内存分配失败,或查看硬件组件是否失败。一些开发人员试图在测试初始化阶段激发真正的环境,以便当从被测试的代码中调用时,它会以错误响应。对我来说,这不切实际,通常太麻烦了。通常,更好的选择是测试特定的、仿造的实现来模拟故障。


4个不那么直率的Mock原因

除了这些明显总是需要模拟的环境的明显情况之外,还有其他一些更微妙的情况,仿造的环境是一个不错的选择。如果我们的测试过程遇到下面列出的任何问题,则表明需要更好地隔离测试的代码。

1.单元测试不可重复

难以实现依赖于易失性的稳定测试。在这种情况下通常会发生的情况是,我们在不更改测试代码或测试代码的情况下收到了不同的测试结果。瞬态可能是依赖系统调用或无法从测试内部控制的外部信号的影响。一个典型的例子是系统时钟——如果测试场景需要在特定的时间点做出反应,那么如果没有能够完全控制对测试代码的间接输入有完全控制权的模拟协作者,则很难实现自动化。

2.测试环境难以初始化

初始化测试环境可能非常复杂。模拟真实的环境,以便他们为测试的代码提供可靠的输入,即使不是不可能,也是一项艰巨的任务。

 组件通常是相互关联的,当尝试初始化一个特定的模块时,我们可能最终会初始化系统的一半。用伪造的实现代替真正的协作者可以降低测试环境初始化的复杂性。

3.测试状态难以确定

在许多情况下,确定测试结论需要在测试执行后检查协作者的状态。使用真正的环境,通常是不可能的,因为在真正的协作者界面中没有合适的访问方法来查询测试后的状态。 

mock代替真正的环境通常可以解决问题,并且我们可以使用各种访问方法来扩展伪造的实现以确定测试结果。

4.测试很慢

在某些情况下,真实环境的响应可能会花费大量时间。当延迟变得不可接受以及何时需要隔离时,并不总是很清楚。测试运行中2分钟的延迟是否可以接受?通常希望能够尽快运行测试套件(也许在每次代码更改之后)。与实际环境的交互导致的大量延迟会使测试套件变得太慢而无法实用。这些真正的环境可能会更快地提高几个数量级,并使测试执行时间达到可接受的水平。


有用的问题,以确定是否要mock

因此,在编写新的CC++单元测试并决定使用原始环境或模拟实现时,请考虑以下四个问题:

  1. 真正的环境是我测试稳定性的风险源吗?
  2. 初始化真正的环境难吗?
  3. 测试后是否可以验证环境的状态,以决定测试状态?
  4. 环境需要多长时间作出回应?

如果我们对环境的了解足够多,可以回答所有这些问题,那么这是一个简单的选择。如果没有,那么我建议您从真正的环境开始,然后尝试回答这四个问题。实际上,这是大多数测试驱动开发(TDD)从业人员在日常工作中应用的方法。这意味着您需要适当注意测试用例并仔细检查它们,直到它们变得稳定为止。

大多数情况下,单元测试的隔离由于要测试的单元的依赖性而变得复杂。在某些情况下,显然需要模拟从属组件,但也需要更微妙的情况。在某些情况下,这不是很明确的方法,它取决于测试环境中依赖项所具有的风险和不确定性。


标签:软件测试技术C/C++

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@capbkgr.cn


为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP