第三章 单元测试

课程来源: 学堂在线 -- 清华大学 -- 软件工程

3.1 单元测试概述

软件设计元素

软件交互设计:分析和理解用户的任务需求,对软件的人机交互、操作逻辑和用户界面进行设计。

系统总体设计:关注系统的质量属性,对整个系统进行模块化分解并选择合适的设计策略

模块设计与实现:应用良好的设计原则,进一步地细化和实现所分解的模块单元(包括数据结构设计、算法设计和数据库设计等)

系统总体设计

系统总体设计是在需求分析的基础上定义系统的设计目标,将整个系统划分成若干子系统或模块,建立整个系统的体系结构,并选择合适的系统设计策略。

一个平面规划的例子

考虑系统的功能需求和非功能需求,将系统划分成更为简单的模块和接口

系统设计目标

在系统设计时,要综合考虑系统资源和业务使用的情况

权衡设计目标

  • 空间与速度
  • 交付时间与功能
  • 交付时间与质量
  • 交付时间与人员

确定子系统或模块

体系结构风格(Architectural Styles) 描述特定系统组织方式的惯用范例,强调软件系统中通用的组织结构

模块分解之后,将模块通过简单的统一接口进行分装,从而减少模块间的依赖程度。

选择系统部署方案

系统部署方案是描述系统运行期间构件和硬件节点之间的关系,在系统设计阶段处理软件/硬件的映射问题,可能会增加新的子系统或模块的定义。

定义设计策略

设计全局控制流

控制流是系统中动作的先后次序。控制流问题需要在设计阶段考虑,其决策取决于操作者或随时间推移所产生的外部事件。

3.2 黑盒测试方法

测试用例的重要性

设计良好的测试用例可以降低软件测试成本(分清先后主次以便更有效地组织测试工作)保证测试工作质量(理清头绪,避免重复和遗漏) 以及评估和检测测试效果(更有效地管理和规划测试工作)

测试用例的概念

为了一个特定目标而设计的一组测试输入、执行条件和预期结果

目的 :为了测试某个程序路径 是否正确或者何时程序是否满足某个特定的程序需求

举例 以移动电话作为软件测试对象

测试用例设计的要求

  • 具有代表性和典型性
  • 寻求系统设计和功能设计的弱点(根据需求规格说明并结合各种可能情况综合考虑测试用例)
  • 既有正确输入也有错误或异常输入
  • 考虑用户实际的诸多使用场景

黑盒测试技术

将测试对象看做一个黑盒子,完全不考虑程序内部的逻辑结构和内部特性 ,只依据程序的需求规格说明书检查程序的功能是否符合它的功能说明

等价类划分

将输入域划分成尽可能少的若干子域,在划分中要求每个子域两两互不相交,每个子域称为一个等价类。

  • 有效等价类 对规格说明有意义、合理的输入数据构成的集合,能够检验程序是否实现了规格说明中预先规定的功能和性能
  • 无效等价类 对规格说明无意义、不合理的输入数据构成的集合,以检查程序是否具有一定的容错性

变量的等价类

取值范围: 在输入条件规定了取值范围的情况下,可以确定一个有效等价类和两个无效等价类。

字符串:在规定了输入数据必须遵守的规则情况下,可确定一个有效等价类(符合规则)和若干个无效等价类(从不同角度违反规则)。

等价类组合

测试用例生成:测试对象通常有多个输入参数,如何对这些参数等价类进行组合测试,来保证等价类的覆盖率,是测试用例设计首先需要考虑的问题。

  • 正面测试用例 所有有效等价类的代表值都集成到测试用例中,即覆盖有效等价类的所有组合。任何一个组合都将设计成一个有效的测试用例。
  • 负面测试用例 无效等价类的代表值只能和其他有效等价类的代表值(随意)进行组合。因此,每个无效等价类将产生一个额外的无效测试用例。

边界值分析

是对输入或输出的边界值 进行测试的一种方法,它通常作为等价类划分法的补充 ,这种情况下的测试用例来自等价类的边界

实例

健壮性测试

作为边界值分析的一个简单的扩充,它除了对变量的5个边界值分析取值外,还要增加一个略大于最大值(max+)以及略小于最小值(min-)的取值, 检查超过极限值时系统的情况。

错误推测法

3.3 白盒测试方法

基本概念

测试覆盖标准

如何选择覆盖标准

  • 处理测试需求的难易程度
  • 生成测试的难易程度
  • 用测试发现缺陷的能力

白盒测试技术

将测试对象看做一个透明的盒子,允许测试人员利用程序内部的逻辑结构 及有关信息,设计或选择测试用例,对程序所有逻辑路径进行测试

可以极大程度增强程序的健壮性

控制流图

控制流图(CFG, Control Flow Graph)是一个过程或程序的抽象表示。

基于控制流的测试

代码覆盖标准

语句覆盖

程序中的每个可执行语句至少被执行一次。

问题分析 测试用例虽然覆盖可执行语句,但无法检查判断逻辑是否存在问题,例如第一个条件判断中"&&"被错误地写成"||"。

语句覆盖是最弱的逻辑覆盖准则。

判定覆盖(分支覆盖)

程序中每个判断 的取真和取假分支至少经历一次,即判断真假值均被满足

问题分析由于大部分判定语句是由多个逻辑条件组合而成,若仅判断其整个最终结果,而忽略每个条件的取值情况,必然会遗漏部分测试路径。

判定覆盖具有比语句覆盖更强的测试能力,但仍是弱的逻辑覆盖。

条件覆盖

每个判断中每个条件的可能取值至少满足一次。

问题分析条件覆盖不一定包含判定覆盖,例如上面测试用例就没有覆盖判断1的T分支和判断2的 F分支。

条件覆盖只能保证每个条件至少有一次为真,而没有考虑整个判定结果。

判定条件覆盖

判断中所有条件的可能 取值至少执行一次,且所有判断的可能结果至少执行一次。

问题分析 判定条件覆盖能够同时满足判定、条件两种覆盖标准。

没有考虑条件的各种组合情况。

条件组合覆盖

判断中每个条件 的所有可能取值组合至少执行一次,并且每个判断本身的结果也至少执行一次。

问题分析条件组合覆盖准则满足判定覆盖、条件覆盖和判定条件覆盖准则。

覆盖了所有组合,但覆盖路径有限。

路径覆盖

覆盖程序中的所有可能的执行路径

问题分析前面的测试用例完全覆盖所有路径,但没有覆盖所有条件组合。

如何看待测试覆盖率

  • 覆盖率数据只能代表测试过哪些代码,不能代表是否测试好这些代码。
  • 较低的测试覆盖率能说明所做的测试还不够,但反之不成立。
  • 路径覆盖 > 判定覆盖 > 语句覆盖
  • 测试人员不能盲目追求代码覆盖率,而应该想办法设计更好的测试用例。
  • 测试覆盖率应达到多少需要考虑软件整体的覆盖率情况以及测试成本。

基本路径测试

循环测试

目的: 检查循环结构的有效性

简单循环
Z路径覆盖下的循环测试

3.4 单元测试工具

Python单元测试工具

测试过程中需要通过属性断言对结果进行判断,以验证结果是否满足需求。

TestCase类提供了多种强大的断言方法,如asserTrue, assertFalse, assertEqual,assertNotEqual, assertIs等。

参考文档 unittest --- Unit testing framework --- Python 3.13.3 documentation

这些断言方法可以在断言的同时加上一个message参数,这样可以使断言的意义明确而且方便维护,在测试失败时抛出可读的信息。

Python单元测试之unittest

  1. import unittest
  2. 定义一个继承自unittest.TestCase的测试用例类
  3. 定义setUp和tearDown,在每个测试用例前后做一些辅助工作
  4. 定义测试用例,名字以test开头
  5. 一个测试用例应该只测试一个方面,测试目的和测试内容应很明确。主要是调用assertEqual、assertRaises等断言方法判断程序执行结果和预期值是否相符
  6. 调用unittest.main()启动测试
  7. 如果测试未通过,会输出相应的错误提示;如果测试全部通过则显示ok,添加-v参数显示详细信息。

Python单元测试之mock

相关推荐
惊讶的猫9 小时前
单元测试的一般步骤
单元测试
Ser@phIn@13 小时前
第六章 敏捷开发与配置管理
软件工程·敏捷流程
悟能不能悟13 小时前
什么是单元测试的“覆盖率”
单元测试
行动π技术博客13 小时前
基于大语言模型的自动化单元测试生成系统及测试套件评估方法
语言模型·单元测试·自动化
Wh0taku1 天前
【软件工程大系】净室软件工程
软件工程
Light603 天前
Python依赖注入完全指南:高效解耦、技术深析与实践落地
python·设计模式·单元测试·fastapi·依赖注入·解耦
lina_mua3 天前
软件工程知识体系全面梳理
软件工程
光头颜4 天前
UML之序列图的消息
软件工程·uml
aiden:)4 天前
设计模式之工厂模式(factory pattern):在商品对象创建系统中的应用
java·开发语言·设计模式·软件工程·软件构建