单元测试知识总结

我们希望每段代码都是自测试的,每次改动之后,都能自动发现对现有功能的影响。

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 {

  @MockBean
  EmployeeService employeeService;

  @Autowired
  MockMvc mockMvc;

  @Test
  public 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 {

  @InjectMocks
  EmployeeService service;

  @Mock
  EmployeeRepository dao;

  @BeforeEach
  public void init() {
    MockitoAnnotations.openMocks(this);
  }

  @Test
  void 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);

    //test
    List<Employee> empList = service.findAll();

    assertEquals(3, empList.size());
    verify(dao, times(1)).findAll();
  }

  @Test
  void 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 {

  @Autowired
  EmployeeRepository employeeRepository;

  @Test
  public 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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/938170.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于AI对话生成剧情AVG游戏

游戏开发这个领域&#xff0c;一直有较高的学习门槛。作为一个非专业的游戏爱好者&#xff0c;如果想要开发游戏&#xff0c;往往受制于游戏引擎的专业程度&#xff0c;难以完成复杂的游戏项目。 AI IDE的诞生&#xff0c;提供了另外的一种思路&#xff0c;即通过AI 生成项目及…

kubeadm安装K8s高可用集群之集群初始化及master/node节点加入calico网络插件安装

系列文章目录 1.kubeadm安装K8s高可用集群之基础环境配置 2.kubeadm安装K8s集群之高可用组件keepalivednginx及kubeadm部署 3.kubeadm安装K8s高可用集群之集群初始化及master/node节点加入集群calico网络插件安装 kubeadm安装K8s高可用集群之集群初始化及master/node节点加入ca…

java后端环境配置

因为现在升学了&#xff0c;以前本来想毕业干java的&#xff0c;很多java的环境配置早就忘掉了&#xff08;比如mysql maven jdk idea&#xff09;&#xff0c;想写个博客记录下来&#xff0c;以后方便自己快速搭建环境 JAVA后端开发配置 环境配置jdkideamavenMySQLnavicate17…

FPC补强板和软硬结合板有什么区别?

柔性印刷电路&#xff08;Flexible Printed Circuit&#xff0c;简称FPC&#xff09;在现代电子设备中有广泛应用&#xff0c;其设计和应用形式多种多样。在FPC的应用中&#xff0c;补强板和软硬结合板是两种常见的增强结构形式&#xff0c;它们在结构、功能和应用方面存在显著…

windows openssl编译x64版libssl.lib,编译x64版本libcurl.lib,支持https,vs2015编译器

不要纠结&#xff0c;直接选择用perl编译&#xff01; 告诫想要用弄成vs编译版的&#xff0c;暂时先别给自己增加麻烦 告诫&#xff0c;以下执行的每一步&#xff0c;都不要纠结 先安装环境 nasm 64位版本 https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/win64/nasm-…

【sizeof】各种数据类型所占空间大小

各种数据类型所占空间大小 文章目录 前言 一、sizeof是什么&#xff1f; 二、使用步骤 1.整型 2.字符型 总结 前言 ‌sizeof在C语言中是一个运算符&#xff0c;用于获取数据类型或变量在内存中所占的字节数。‌它可以在编译时计算数据类型或变量的内存大小&#xff0c;而…

gitlab仓库API操作

几年没接触gitlab了&#xff0c;新版本装完以后代码提交到默认的main分支&#xff0c;master不再是主分支 项目有几十个仓库&#xff0c;研发提交代码后仓库地址和之前的发生了变化 先修改Group的默认分支&#xff0c;不会影响已存在的项目 修改gitlab全局的默认分支 这就引…

Gitlab服务管理和仓库项目权限管理

Gitlab服务管理 gitlab-ctl start # 启动所有 gitlab 组件&#xff1b; gitlab-ctl stop # 停止所有 gitlab 组件&#xff1b; gitlab-ctl restart # 重启所有 gitlab 组件&#xff1b; gitlab-ctl status …

睡岗和玩手机数据集,4653张原始图,支持YOLO,VOC XML,COCO JSON格式的标注

睡岗和玩手机数据集&#xff0c;4653张原始图&#xff0c;支持YOLO&#xff0c;VOC XML&#xff0c;COCO JSON格式的标注 数据集分割 训练组70&#xff05; 3257图片 有效集20&#xff05; 931图片 测试集10&#xff05; 465图片 预处理 没有采用任何预处…

vue响应式数据-修改对象的属性值,视图不更新

如图&#xff1a; 一&#xff1a;问题是&#xff1a; 我把数据处理后能console.log()打印出来&#xff0c;但是页面的内容不能同步的更新渲染&#xff1b; 二&#xff1a;要求&#xff1a; 在数组循环列表里面&#xff0c;我点击单个的item按钮时&#xff0c;需要实时加载进度…

HuLa——一款基于 Tauri+Vue3 构建的桌面即时通讯应用

文章目录 一、HuLa简介二、技术栈介绍三、安装运行四、界面体验五、开源地址 一、HuLa简介 HuLa 是一个基于 Tauri、Vite 5、Vue 3 和 TypeScript 构建的即时通讯系统。它利用了 Tauri 的跨平台能力和 Vue 3 的响应式设计&#xff0c;结合了 TypeScript 的类型安全特性和 Vite…

云计算HCIP-OpenStack03

书接上回&#xff1a; 云计算HCIP-OpenStack02-CSDN博客 10.KeyStone keystone-Openstack&#xff0c;IAM服务&#xff08;统一身份认证&#xff09;-云服务 建议先去了解Hadoop&#xff08;大数据生态系统&#xff09;中的kerberos&#xff08;LDAPkerberos的鉴权机制&#xf…

【YOLO 项目实战】(10)YOLO8 环境配置与推理检测

欢迎关注『youcans动手学模型』系列 本专栏内容和资源同步到 GitHub/youcans 【YOLO 项目实战】&#xff08;1&#xff09;YOLO5 环境配置与检测 【YOLO 项目实战】&#xff08;10&#xff09;YOLO8 环境配置与推理检测 【YOLO5 项目实战】&#xff08;10&#xff09;YOLO8 环境…

Vue 3: 通过图片链接获取图片颜色,间接设置背景颜色

在现代Web开发中&#xff0c;动态获取和处理图像数据是一个常见的需求。例如&#xff0c;你可能希望自动提取一张图片的主色调&#xff0c;以便根据这些颜色进行UI主题调整或其他视觉效果的处理。本文将介绍如何在Vue 3项目中&#xff0c;通过一个图片链接获取图片的颜色信息。…

请确保 $(OutDir)、$(TargetName) 和 $(TargetExt) 属性值与 %(Link.OutputFile) 中指定的值匹配

vs版本升级时&#xff0c;编译时会出现上述问题&#xff0c;如原来在2017下编译的程序&#xff0c;后来改用2019&#xff0c;出现上述问题。需要在解决方案-通用属性-调试源文件下变更相应设置。

FFmpeg第一话:FFmpeg 简介与环境搭建

FFmpeg 探索之旅 一、FFmpeg 简介与环境搭建 二、FFmpeg 解码详解 第一话&#xff1a;FFmpeg 简介与环境搭建 FFmpeg 探索之旅一、前言二、FFmpeg 是什么&#xff1f;三、简单介绍其历史背景四、为什么用 C学习 FFmpeg&#xff1f;&#xff08;一&#xff09;高性能优势&#…

【功能安全】软件安全架构

目录 01 软件安全架构介绍 02 软件架构设计模板 03 软件架构设计示例 01 软件安全架构介绍

OpenLinkSaas 2025年1月开发计划

先来看看OpenLinkSaas的大目标 在OpenLinkSaas的产品目标中&#xff0c;让开发人员更加方便的使用云资源是目标之一。通过各大云厂商的API&#xff0c;来可视化云上基础设施的数据是远远不够的。我们准备在2025年1月份增加方便管理和运营研发场景下服务器的能力。 这部分的功能…

【Verilog】实验九 存储器设计与IP调用

一、实验目的 1. 掌握单端口RAM和ROM原理和设计方法。 2. 掌握单端口RAM和ROM的IP生成和调用方法。 2. 掌握ModelSim和VIVADO工具软件。 3. 掌握基本的测试代码编写和FPGA开发板使用方法。 二、实验环境 1. 装有ModelSim和VIVADO的计算机。 2. Sword实验系统。 三、实验…

元力音乐 1.2.2 | 完全免费无广告的无损音乐听歌下载工具

元力音乐是一款音乐听歌和下载工具&#xff0c;提供完全免费且没有任何广告弹窗的用户体验。内置两条线路&#xff0c;用户可以无限次下载无损音质音乐。作者承诺永久免费并长期维护此应用。此外&#xff0c;它还支持导入歌单功能&#xff0c;让用户能够轻松管理和下载喜爱的音…