什么是模块测试?定义、示例

⚡ 智能摘要

模块测试检查的是单个子程序、子例程、类和过程,而不是整个程序,因此缺陷会在一个较小的、易于理解的代码块中显现出来,从而更容易定位和修复。

  • 🎯 目的: 目的是找出模块中的错误,而不是证明模块能够正常工作。
  • 性取向: 该技术主要采用白盒测试,并辅以根据规范绘制的黑盒测试案例。
  • 并行性: 可以同时测试多个模块,从而缩短整体测试时间。
  • 🔗 两种方法: 模块可以逐步组合,也可以一次性非增量组合。
  • 🧰 脚手架: 驱动程序向模块提供测试数据,而存根则代表它调用的模块。
  • ???? 产权: 测试人员在编码完成后编写模块测试,而开发人员在编码过程中编写单元测试。
  • ⚠️ 面临的挑战: 非增量式工作、对测试替身的误解以及频繁的调试消耗了大部分精力。

模块测试详解:方法、驱动程序、存根和比较

什么是模块测试?

模块测试 模块化测试是一种软件测试类型,它检查程序中的各个子程序、子例程、类或过程。与一次性测试整个软件程序不同,模块化测试建议测试程序的较小组成部分。

模块测试主要面向白盒测试。模块测试的目的并非验证模块是否正常运行,而是验证模块是否存在错误。这种颠倒的逻辑至关重要:一次测试如果什么都没发现,那么它所验证的信息就非常有限;而一次测试如果发现了缺陷,那么它就完成了任务。

模块级测试还允许在测试过程中引入并行性,因为它创造了同时测试多个模块的机会,而无需等待完整的构建过程。

为什么要进行模块测试

建议进行模块化测试,因为它改变了缺陷检测的经济效益。

  • 在程序的较小部分中发现错误或漏洞的概率会更高。
  • 该方法可以同时测试多个模块,因此支持并行测试。
  • 由于每个模块都是独立进行推理的,因此测试的复杂性很容易管理。
  • 发现一个模块内部存在缺陷 trac只需编写少量代码,调试时间即可大幅缩短。

如何进行模块测试?

设计 测试用例 是模块测试的重要组成部分。在设计模块测试的测试用例时,测试人员必须考虑两件事。

  • 模块规格
  • 模块的源代码

使用以下一种或多种方法分析模块的逻辑: 白盒 方法,然后通过应用这些方法来补充这些测试用例。 黑盒子 模块规范的方法。实际值与所选路径同样重要,因此请做好准备。 测试数据 与案件同时进行,而不是事后进行。

测试用例设计完成后,下一步是将各个模块组合起来进行测试。所采用的方法有两种: 增量 或者 非增量式 方法。

  • 非增量法 所有模块均独立测试。程序首先将所有模块组合起来,然后测试整个程序。
  • 增量法 — 每个模块先进行测试,然后逐步添加到测试集合中。它执行分步复测。
  • 增量测试有两种方法, 自上而下自下而上 测试。
  • 要使用选定的数据执行该模块,需要一个驱动程序来提供测试数据、监控执行过程并捕获结果。

这两种方法之间的选择是在设置工作量和可诊断性之间进行权衡。

方面 增量法 非增量法
混合型皮肤 一次添加一个模块,并将其添加到已测试的集合中。 所有模块组合在一起,然后一起进行测试。
需要脚手架 更多驱动程序和存根,逐步编写 由于使用了真实模块,因此测试替身数量较少。
误隔离 强——模块新增的故障点 弱点——故障可能源于任何地方。
最适合 包含许多交互模块的大型构建 模块少、耦合度低的小型程序

模块测试中的驱动程序和桩程序

上面提到的驱动程序是成对出现的一半。由于被测模块很少位于调用链的顶端或底端,测试人员会用虚拟代码来代替其两侧缺失的代码。

  • 驱动器 — 替换被测模块上方的调用模块。它提供测试数据、调用模块、监控执行过程并捕获结果。自底向上的测试依赖于驱动程序,因为底层模块比上层模块更早准备就绪。
  • 存根 — 替换被测模块下方的已调用模块。它接受调用并返回一个固定的、已知的响应,以便被测模块能够完成其执行路径。自顶向下测试依赖于桩模块,因为上层模块会先准备就绪。

一个已完成的案例将这种配对具体化。如果支付计算模块已完成,但调用它的结账页面尚未完成,则驱动程序会向该模块提供一组订单总额,并记录返回的结果。如果该模块调用的税务查询服务也尚未完成,则一个占位符会返回一个固定的税率,以便计算仍然可以运行。这两个脚手架都不会交付;一旦真正的模块完成,它们都会被丢弃,这就是为什么对测试替身的误解在后面被列为反复出现的挑战。

模块测试的示例技巧

以下是一些在执行模块测试之前需要考虑的提示。

  • Rev使用前请查看测试用例。
  • 避免对差异来源产生混淆。
  • 使用自动化测试工具。
  • 检查哪些变量应该保持不变。
  • 在测试人员之间交换模块,以避免进行自测。
  • 重复使用测试用例。

第五条建议虽然篇幅不长,但其重要性不容小觑。如果开发人员只测试刚刚编写的模块,就会重复导致缺陷的相同假设,因此,让不同的开发人员轮流测试模块是提升质量最经济有效的方法之一。

单元测试与模块测试

这两个术语在许多团队中可以互换使用,但它们的作者和范围却有所不同。

模块测试 单元测试
模块测试是开发人员编写一些代码后,由测试人员编写的一组测试 单元测试 是开发人员在软件开发过程中编写的一系列测试的集合。
模块测试可能涉及合并单元测试 单元测试可以单独测试各个单元。

模块测试、组件测试和集成测试

模块测试还与两个容易混淆的相邻层级相邻。表格根据测试对象和通常执行测试的人员对它们进行了区分。

方面 模块测试 组件测试 整合测试
正在测试中 一个子程序、类或过程 一个独立的组件及其直接依赖项 组合模块之间的接口
普通所有者 测试人员,在代码编写完成后 测试仪 集成测试员
脚手架系统 驱动单元和存根 外部依赖项的存根 双打测试赛人数逐渐减少
缺陷暴露 模块内部逻辑错误 组件中的行为错误 接口和数据传递错误

日常使用 组件测试 模块测试通常被视为同一项活动,而 集成测试 只有当各个模块都独立通过后,课程才会开始。

模块测试中的挑战

这些是团队在引入模块测试时最常遇到的挑战。

  • 非增量测试需要更多工作 — 首先将所有步骤结合起来,意味着一次失败就可能导致测试人员不得不重新执行整个程序。
  • 对测试替身的误解 — 返回不切实际值的存根产生绿色运行,但这并不能证明任何事情。
  • 调试测试经常 — 脚手架代码本身就存在缺陷,修复驱动程序所花费的时间就无法用于测试模块。
  • 需要理解代码 — 白盒测试意味着无法阅读模块的测试人员无法为其设计有意义的测试用例。

常见问题

xUnit 系列涵盖了大多数编程语言,它使用模拟库提供存根,并提供覆盖率工具来显示已执行的路径。选择 xUnit 取决于模块的编程语言,而不是测试级别。

模型读取模块源代码,枚举分支,并为每个分支提出一个案例,包括手动处理经常遗漏的边界值。 Rev仍然需要查看,因为生成的案例断言的是代码实际执行的操作,而不是规范要求的操作。

是的,这类辅助工具在脚手架场景中表现最佳,因为驱动程序或存根代码是结构已知的重复代码。返回值仍然需要人工判断,因为看似合理的存根代码可能隐藏着正在查找的缺陷。

模块中的每个分支和每个边界至少都执行过一次即可。仅以百分比为目标具有误导性,因为即使语句覆盖率很高,仍然可能遗漏一些决策结果。

模块编译之后、接口协同工作之前,这是对交付代码进行的第一层测试,因此在此阶段发现的缺陷不会进入集成或系统阶段。

遵循现有代码。自顶向下的方法适用于控制逻辑先编写、底层模块先进行存根的项目;自底向上的方法适用于实用模块先部署、驱动程序调用它们的项目。

该模块编译正常,其规范可用,其依赖项要么存在要么已存根,测试数据也已准备就绪。如果没有规范,练习就变成了对代码的描述。

测试永远无法证明一个模块完全没有缺陷,只能证明它经受住了所有测试用例的考验。因此,设计旨在破坏模块的测试用例比设计预期通过的测试用例能提供更多信息。

总结一下这篇文章: