单元测试知识总结
我们希望每段代码都是自测试的,每次改动之后,都能自动发现对现有功能的影响。
1 测试要求
在对软件单元进行动态测试之前,应对软件单元的源代码进行静态测试;
应建立测试软件单元的环境,如数据准备、桩模块、模拟器。
对软件设计文档规定的软件单元的功能、性能、接口等应逐项进行测试。
每个软件特性应至少被一个正常测试用例和一个被认可的异常测试用例覆盖
测试用例的输入应至少包括 有效等价类值、无效等价类值 和 边界数据值;
语句覆盖率要达到要求(如70%);
分支覆盖率要达到要求(如70%);
对输出数据正确与否 及 其格式进行测试。
2 单元测试任务
模块接口测试;
模块局部数据结构测试;
模块边界条件测试;
模块中独立执行路径测试;
模块的错误处理路径测试。
3 静态分析
控制流分析:根据设计文档定义的控制流程,分析被测试程序是否按要求运行。
数据流分析:用控制流程图来分析数据发生的异常情况,这些异常包括被初始化、被赋值或被引用过程中行为序列的异常。数据流分析也作为数据流测试的预处理过程
推荐使用“TDD测试驱动开发”的方式,开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么代码产品,之后再开始真正的业务需求开发。
4 动态测试
4.1 功能测试
功能测试是对软件设计中的软件单元逐项进行的测试,以验证其功能是否满足要求。
功能测试一般需进行:
用正常值的等价类输入数据值测试;
用非正常值的等价类输入数据值测试;
进行每个功能的合法边界值和非法边界值输入的测试;
用一系列真实的数据类型和数据值运行,测试超负荷、饱和及其他“最坏情况”的结果
4.2 接口测试
接口测试是对软件设计文档中的外部/内部接口逐项进行的测试。
接口测试一般需进行:
测试所有外部/内部接口,检查接口信息的格式和内容;
对每一个外部/内部输入/输出接口必须进行正常和异常情况的测试
4.3 边界测试
边界测试是对软件处在边界或端点情况下运行状态的测试。
边界测试一般需进行:
软件的输入域或输出域的边界或端点的测试;
状态转换的边界或端点的测试;
功能界限的边界或端点的测试;
性能界限的边界或端点的测试;
容量界限的边界或端点的测试。
4.4 逻辑测试
逻辑测试是测试程序逻辑结构的合理性、实现的正确性。逻辑测试应由测试人员利用程序内部的逻辑结构及有关信息,设计或选择测试用例,对程序所有逻辑路径进行测试。通过在不同点检查程序的状态,确定实际的状态是否与预期的状态一致。
逻辑测试应满足覆盖率的要求,一般需进行:
- 语句覆盖;
- 分支覆盖;
- 条件覆盖;
- 条件组合覆盖;
- 路径覆盖。
5 单元测试用例设计方法
等价类划分、边界值分析、逻辑覆盖法、基本路径测试法
5.1 等价类划分
等价类划分的方法是把程序的输入划分成若干等价类部分,然后从每个部分中选取少数代表性数据当作测试用例。
确定等价类原则:
- 如果输入变量定义了一个取值范围(例如正常取值为[1,999]),那么就应确定一个有效等价类(1≤输入≤999),以及两个无效等价类(输入<1,输入>999);
- 如果输入变量为枚举类型,或对于规定的有限输入值集合分别进行不同的处理,那么应对每一个输入确定一个有效等价类,并确定一个无效等价类;
- 如果对输入变量进行逻辑判断,那么应对逻辑条件满足与否分别确定一个有效等价类和一个无效等价类;
- 如果输入变量作为数组下标或指针使用,那么应根据规定的数组元素个数,分别确定有效等价类和无效等价类。
5.2 边界值分析
- 如果规定了变量的输入范围,那么应该对范围的边界设计测试用例;对于未具体规定取值范围的输入变量,应考虑对变量数据类型所能达到的最大范围的上下限设计测试用例;
- 如果规定了数组、循环逻辑次数等数量,应针对最小、最大数量值的边界设计测试用例;
- 如果规定了输出变量的范围,还应考虑针对输出变量范围边界所对应的输入变量数值设计测试用例;

- 对各边界条件的上点和离点作为测试输入数据
- 如果输入条件规定了值的个数,则用最大个数,最小个数,比最小个数少一,比最大个数多一的数作为测试数据
- 如果程序的规格说明给出的输入域或输出域是有序集合,则应选取集合的第一个元素和最后一个元素作为测试用例
5.3 逻辑覆盖法
逻辑覆盖法是根据程序内部逻辑覆盖满足性设计测试用例的白盒测试方法。
(1)语句覆盖:就是设计若干个测试用例,运行被测程序,使得每一可执行语句至少执行一次。
(2)分支覆盖:(判定覆盖)使设计的测试用例保证程序中每个判断的每个取值分支至少经历一次。但若程序中的判定是有几个条件联合构成时,它未必能发现每个条件的错误;
(3)条件覆盖:条件覆盖是指选择足够的测试用例,使得运行这些测试用例时,判定中每个条件的所有可能结果至少出现一次,但未必能覆盖全部分支;
(4)分支 / 条件覆盖:分支/条件覆盖是使判定中每个条件的所有可能结果至少出现一次,并且每个分支本身的所有可能结果也至少出现一次;
(5)条件组合覆盖:条件组合覆盖是使每个分支中条件结果的所有可能组合至少出现一次,因此分支本身的所有可能结果也至少出现一次
(6)路径覆盖:是每条可能执行到的路径至少执行一次。
补充:
(1)语句覆盖在所有的测试方法中是一种最弱的覆盖。
(2)判定覆盖和条件覆盖比语句覆盖强,满足判定/条件覆盖标准的测试用例一定也满足判定覆盖、条件覆盖和语句覆盖
(3)路径覆盖也是一种比较强的覆盖,但未必考虑判定条件结果的组合,并不能代替条件覆盖和条件组合覆盖。
举个例子吧:
if A and B then Action1
if C or D then Action2语句覆盖最弱,只需要让程序中的语句都执行一遍即可 。上例中只需设计测试用例使得A=true B=true C=true 即可。分支覆盖又称判定覆盖:使得程序中每个判断的取真分支和取假分支至少经历一次,即判断的真假均曾被满足。上例需要设计测试用例使其分别满足下列条件即可(1)A=true,B=true,C=true,D=false(2)A=true,B=false,C=false,D=false。条件覆盖:要使得每个判断中的每个条件的可能取值至少满足一次。上例中第一个判断应考虑到A=true,A=false,B=true,B=false第二个判断应考虑到C=true,C=false,D=true,D=false,所以上例中可以设计测试用例满足下列条件(1)A=true,B=true,C=true,D=true(2)A=false,B=false,C=false,D=false。路径覆盖:要求覆盖程序中所有可能的路径。所以可以设计测试用例满足下列条件(1)A=true,B=true,C=true,D=true(2)A=false,B=false,C=false,D=false(3)A=true,B=true,C=false,D=false(4)A=false,B=false,C=true,D=true。不论那种覆盖方法,都不能保证程序的正确性。
一般测试书中讲白盒测试的逻辑覆盖部分时都会对这几种覆盖作比较,而且都给出了例子。
我们要求的是分支覆盖。
5.4 基本路径测试

上图中,独立路径有5条,即需要有5个测试用例覆盖。
我们会统计独立路径的覆盖率。
代码规范中对方法复杂度有要求,一个方法的复杂度太高,容易出错且难以测试。
6 单元测试的实现方法
6.1 mock
单元测试不是集成测试,只测试自身的逻辑;因此,我们使用mockito库,模拟返回外部接口或者其它函数的结果
6.3 数据准备
使用@Sql
7 单元测试与集成测试
写单元测试时,容易有一个误区,就是都写的集成测试,而没有对某个方法写单元测试,这其实是一种想要偷懒但其实低效的方法,包括编写、运行、效果都是低效的。
对每个层进行特定的测试方法,会更新高效。
单元测试与集成测试的比例大概是3:1。使用单元测试去覆盖分支,效率会更高。
使用gradle 的JVM Test Suite Plugin划分单元测试与集成测试集,分开执行,单元测试开启gradle的并行运行模式。
7.1 controller层
这层主要,测试参数校验。
需要使用“@WebMvcTest”注解。
mock掉service
@WebMvcTest(EmployeeController.class)
public class StandaloneControllerTests {@MockBeanEmployeeService employeeService;@AutowiredMockMvc mockMvc;@Testpublic void testfindAll() throws Exception {Employee employee = new Employee("Lokesh", "Gupta");List<Employee> employees = Arrays.asList(employee);Mockito.when(employeeService.findAll()).thenReturn(employees);mockMvc.perform(get("/employee")).andExpect(status().isOk()).andExpect(jsonPath("$", Matchers.hasSize(1))).andExpect(jsonPath("$[0].firstName", Matchers.is("Lokesh")));}}
7.2 service层
主要的业务逻辑层,需要对各个业务分支代码进行测试,是单元测试最多的层。
使用mock,不需要使用“@SpringBootTest”注解,运行和编写的效率更高。
@ExtendWith(MockitoExtension.class)
public class ServiceTests {@InjectMocksEmployeeService service;@MockEmployeeRepository dao;@BeforeEachpublic void init() {MockitoAnnotations.openMocks(this);}@Testvoid testFindAllEmployees() {List<Employee> list = new ArrayList<Employee>();Employee empOne = new Employee("John", "John");Employee empTwo = new Employee("Alex", "kolenchiski");Employee empThree = new Employee("Steve", "Waugh");list.add(empOne);list.add(empTwo);list.add(empThree);when(dao.findAll()).thenReturn(list);//testList<Employee> empList = service.findAll();assertEquals(3, empList.size());verify(dao, times(1)).findAll();}@Testvoid testCreateOrSaveEmployee() {Employee employee = new Employee("Lokesh", "Gupta");service.save(employee);verify(dao, times(1)).save(employee);}
}
7.3 dao层
需要准备数据到数据库,测试复杂sql编写是否正确。
这个层的测试分支覆盖情况工具会统计的不全面,特别是使用mysql的时候,需要开发自觉测试各种情况。
注解@AutoConfigureTestDatabases可以配置使用内存数据库
@DataJpaTest 会禁用auto-configuration,只配置JPA测试需要用到的配置。
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class DaoTests {@AutowiredEmployeeRepository employeeRepository;@Testpublic void testCreateReadDelete() {Employee employee = new Employee("Lokesh", "Gupta");employeeRepository.save(employee);Iterable<Employee> employees = employeeRepository.findAll();Assertions.assertThat(employees).extracting(Employee::getFirstName).containsOnly("Lokesh");employeeRepository.deleteAll();Assertions.assertThat(employeeRepository.findAll()).isEmpty();}
}
7.4 其它工具类
使用utils类
大部分都是单元测试,尽量不要添加“@SpringBootTest”注解
7.5 集成测试
测试整个路径,包括从controller接收请求并返回,到数据库修改。
使用@SpringBootTest
相关文章:
单元测试知识总结
我们希望每段代码都是自测试的,每次改动之后,都能自动发现对现有功能的影响。 1 测试要求 在对软件单元进行动态测试之前,应对软件单元的源代码进行静态测试; 应建立测试软件单元的环境,如数据准备、桩模块、模拟器…...
Android:使用Service处理息屏后的WebSocket的服务端推送消息并传递给前端
前言 之前我们在使 RESTful 访问服务端时,一般都是客户端请求服务端应答的方式,这种通讯方式,对于需要持续获取数据的情形都是采用轮询的方式,但是这种方式对两边的性能消耗很大,特别是服务端的压力很大。现在当我们使…...
Git Bash Here 中文显示乱码的处理方法
在使用"open Git Bash Here"时,遇到中文显示乱码问题。 原因:通常是由于编码设置不正确导致的。 open Git Bash Here —>鼠标右击空白处,点击「选项」|或「Options」 在「文本」或 「Text」选项卡中,找到"local…...
FreeBSD安装教程
FreeBSD 是一个功能强大且可靠的开源 UNIX 操作系统,适合服务器和桌面环境。本文将介绍如何安装 FreeBSD,从系统准备到基础设置,为你快速上手提供帮助。 一、准备工作 1. 硬件要求 CPU:支持 x86 或 AMD64 架构的处理器。 内存&a…...
Loki 各模式简介
目录 Loki 部署模式 单片模式 简单可扩展 微服务模式 Loki 部署模式 Loki 是一个由许多微服务组成的分布式系统。它还具有独特的构建模型,其中所有这些微服务都存在于同一个二进制文件中。 您可以使用命令行标志配置单个二进制文件的行为-target,以指…...
MySQL八股-全局锁,表级锁,表锁,元数据锁,意向锁,行级锁,行锁,间隙锁,临键
文章目录 全局锁表级锁表锁(表级锁)元数据锁(MDL,Meta Data Lock,表级锁)元数据锁演示元数据锁兼容的情况元数据锁互相阻塞的情况 意向锁(Intention lock,表级锁)意向锁分类意向锁演示:意向共享锁(**IS**)与…...
(四)Spring Cloud Alibaba 2023.x:高效构建 Gateway 网关服务
目录 前言 准备 项目集成 pom.xml引入依赖 启动类 yml文件添加网关配置 修改消费者FeignService类 结果验证 前言 Spring cloud alibaba 体系中构建微服务,我们使用Spring Cloud Gateway 作为服务网关, Gateway是Spring 官方推出的一款基于 Web…...
Android XR 是什么?解释它的功能、设备、开发工具等
什么是“Android XR”? Android XR是最新配备AI的OS(操作系统),兼容耳机和眼镜(AR眼镜)。 沉浸式剧场 从视频列表中选择... 您可以体验完全身临其境的视频观看体验。 无限工作空间 您的现实世界将成为您…...
【算法】实体关系抽取
✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…...
Codeforces Round 993 (Div. 4)题解
A. Easy Problem 思路:经过看了一眼,我们发现,ab的和一定是n,且两个都是正整数, 所以a的范围就是从1~n-1 所以输出n-1即可 #include<bits/stdc.h> using namespace std; #define int long long int t; int n…...
【计算机网络】期末考试预习复习|中
作业讲解 转发器、网桥、路由器和网关(4-6) 作为中间设备,转发器、网桥、路由器和网关有何区别? (1) 物理层使用的中间设备叫做转发器(repeater)。 (2) 数据链路层使用的中间设备叫做网桥或桥接器(bridge)。 (3) 网络层使用的中间设备叫做路…...
从零用java实现 小红书 springboot vue uniapp (4)个人主页优化
前言 移动端演示 http://8.146.211.120:8081/#/ 前面的文章我们基本完成了详情页开发 今天我们具体的去进行实现个人中心 并且分享我开发时遇到的问题 首先先看效果 我们对布局整体规划一下 个人名片 半透明背景 刚开始我用的是 <view style"background-image: ur…...
为“行车大脑”降温:Simdroid-EC助力汽车ECU设计研发
ECU(Electronic Control Unit,电子控制单元)被誉为汽车的行车大脑,在工作时会产生大量的热量,而其散热存在以下难题:一是工作环境恶劣,ECU常处于高温环境中;二是ECU所处的空间较为狭…...
视频汇聚平台:Liveweb视频流媒体平台视频监控系统解决方案
数字化技术在安防领域的广泛应用已经成为公安等重要执法部门的重要趋势,主要得益于无线网络通信技术和计算机技术的快速进步。传统的视频监控系统存在诸多局限,例如只能进行现场监视,报警信息传输简单,无法远距离传输视频信号&…...
通过解调使用正则化相位跟踪技术进行相位解包裹
1. 绪论 光学计量学通常使用光学干涉仪来测量各种物理量。1,2 根据应用的不同,可以使用多种类型的干涉仪,但它们的共同目标是产生一个由被测物理量调制的条纹图案。使用这种光束编码程序可以检测到的物理量范围非常广:深度测量、应变分析、温…...
VMware替代 | 双一流大学采用ZStack ZSphere虚拟化平台加速医学应用算法分析
某双一流大学医学部在面对日益增长的医学应用算法分析需求时,选择采用ZStack ZSphere虚拟化平台,以满足其高性能计算和GPU业务应用的迫切需求。该平台凭借其轻量化、卓越性能及易用性,成功解决了医学部在虚拟化及GPU应用场景中的挑战。随着平…...
UNIAPP框架uView初步集成与开发设计
uView UI,是uni-app生态最优秀的UI框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水。本文章分享UNIAPP集成使用uView页面动态开发设计。 一、使用HBuilder X 直接导入插件,下载后重启 uView - DCloud 插件市场 二、配置样…...
C05S08-LVS负载均衡
一、LVS 1. LVS概述 LVS(Linux Virtual Server、Linux虚拟服务)是一种基于Linux系统集群的负载均衡方案,属于四层的负载均衡。 集群:将相同组件部署在不同的服务器上,提供统一的服务,以及同样的功能&…...
C 语言代码诗韵:数字功能的雅集华章
函数基本操作练习 主要内容: 本任务主要练习函数的申请、定义、调用等,主要包含以下功能: 1)编写函数,输入一个整数,求各个数字之和; 2)编写函数,计算1!2&…...
ps案例制作
宣传海报 暖色调海报商品展示图...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...
零知开源——STM32F103RBT6驱动 ICM20948 九轴传感器及 vofa + 上位机可视化教程
STM32F1 本教程使用零知标准板(STM32F103RBT6)通过I2C驱动ICM20948九轴传感器,实现姿态解算,并通过串口将数据实时发送至VOFA上位机进行3D可视化。代码基于开源库修改优化,适合嵌入式及物联网开发者。在基础驱动上新增…...
React从基础入门到高级实战:React 实战项目 - 项目五:微前端与模块化架构
React 实战项目:微前端与模块化架构 欢迎来到 React 开发教程专栏 的第 30 篇!在前 29 篇文章中,我们从 React 的基础概念逐步深入到高级技巧,涵盖了组件设计、状态管理、路由配置、性能优化和企业级应用等核心内容。这一次&…...
java高级——高阶函数、如何定义一个函数式接口类似stream流的filter
java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用(Math::max) 2 函数接口…...
密码学基础——SM4算法
博客主页:christine-rr-CSDN博客 专栏主页:密码学 📌 【今日更新】📌 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 编辑…...
边缘计算网关提升水产养殖尾水处理的远程运维效率
一、项目背景 随着水产养殖行业的快速发展,养殖尾水的处理成为了一个亟待解决的环保问题。传统的尾水处理方式不仅效率低下,而且难以实现精准监控和管理。为了提升尾水处理的效果和效率,同时降低人力成本,某大型水产养殖企业决定…...
