1 概述

在还没有写什么代码之前,就引入单元测试,是要强调单元测试的重要性。当一套代码的生命周期比较长的时候,单元测试更加重要。生命周期长的代码,不管是产品人员还是开发人员,可能都会换了一批又一批,维护才是成本的大头。后来的人缺乏这套代码的历史知识,改起来就会bug频出,质量堪忧。如果有单元测试代码,则每次的修改如果有问题,就能够通过单元测试代码暴露出来,这样改代码会比较让人放心。但单元测试代码是一项做了则太平无事看不出作用的事情,但不做则经常要灭火而追悔莫及的事情。如果公司不强制要求或者工期比较紧张的,很可能是被忽略的,等到代码积累多了、历史知识又丢失了不少的时候,再来想补,就困难重重了。

所以,在此要先引入单元测试的基础设施,并在写代码的时候都加上单元测试,以达到编写代码达到100%的测试覆盖率。这个“100%”如果变成什么“80%”之类的,效果就会差很多,因为哪些测了哪些没测就分不清楚了,就很难监督单元测试的执行了。如果实在有些是测不了的,那么应该在工具中排除掉,排除掉的代码应该尽量少,在此基础上保持“100%”的覆盖率,使得能够比较好的监督单元测试有没有在正常执行。

2 单元测试

2.1 引入依赖

Springboot已经对测试给出了自己的推荐,也是目前比较流行的选择,如果没有什么特殊需求的话,直接选用即可。

首先,在<dependencies>中引入test的依赖:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>

就是这样一个依赖,就基本足够了。

2.2 具体依赖

找到 https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-starter-test/2.7.18/spring-boot-starter-test-2.7.18.pom 文件,看看里面的具体依赖:

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.7.18</version><scope>compile</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-test</artifactId><version>2.7.18</version><scope>compile</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-test-autoconfigure</artifactId><version>2.7.18</version><scope>compile</scope></dependency><dependency><groupId>org.assertj</groupId><artifactId>assertj-core</artifactId><version>3.22.0</version><scope>compile</scope></dependency><dependency><groupId>org.hamcrest</groupId><artifactId>hamcrest</artifactId><version>2.2</version><scope>compile</scope></dependency><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.8.2</version><scope>compile</scope></dependency><dependency><groupId>org.mockito</groupId><artifactId>mockito-core</artifactId><version>4.5.1</version><scope>compile</scope></dependency><dependency><groupId>org.mockito</groupId><artifactId>mockito-junit-jupiter</artifactId><version>4.5.1</version><scope>compile</scope></dependency>
</dependencies>

上面是一些主要依赖的摘录,前三个是引入springboot的基础,单元测试库junit已经是事实标准,通过junit-jupiter一起引入;断言库同时引入了assertj和hamcrest,它们各有各的优势,这里优先使用assertj;mock库则选用了mockito。mock对象,进行单元测试,最后断言结果,这是测试的三个步骤,分别使用了对应的库,这几种库的语法需要学一学。

单元测试的代码要求逻辑简单,就做上面三件事情,不要有什么业务逻辑,单元测试之间也不要有什么关系,保证单元测试代码简单,因为没有人再来测试单元测试代码了。

3 测试覆盖率

单元测试是一个做了不好看到效果,如果没有限制,那做多多少全凭开发的心情,那大概率很快就会荒废掉。所以需要有监督方式,其中就是引入测试覆盖率工具,这里选用JaCoCo,通过它来生成测试覆盖率,每次写完代码都应该检查测试覆盖率,确保单元测试覆盖所有预期的代码。

3.1 工具引入

引入JaCoCo,只需要在pom.xml中的里增加插件,版本根据情况选比较新的:

<plugin><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artifactId><version>0.8.13</version>
</plugin>

3.2 生成测试覆盖率

3.2.1 IDEA生成测试覆盖率

在IDEA中,选中单元测试用例类(可以整个目录),然后右键选择菜单“Run Tests in project_name with Coverage”:

IDEA会执行对应的测试用例,如果是在测试的根目录执行,则可以得到所有测试用例的测试覆盖率,并把结果展示到一个“Coverage”窗口里:

针对那些覆盖率不到100%的类进行检查和补充测试用例,如果要看详情则可以导出报告:

导出的报告里有个index.html,打开该文件会展示各个类的测试覆盖率,选择覆盖率不到100%的类,里面是绿色的则是覆盖的,红色的则是未覆盖的,针对红色部分的代码进行补充测试用例。

3.2.2 命令行生成测试覆盖率

IDEA会在底下默默做一些事情,让操作比较简单,这对开发人员比较友好。但如果想在持续集成工具如Jenkins上也能够生成测试覆盖率,那么还需要增加点配置:

<plugin><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artifactId><version>0.8.13</version><executions><execution><id>prepare-agent</id><goals><goal>prepare-agent</goal></goals></execution><execution><id>report</id><phase>test</phase><goals><goal>report</goal></goals><configuration><outputDirectory>${project.build.directory/}coverage_reports</outputDirectory></configuration></execution></executions>
</plugin>

上面<plugin>配置增加了一个<execution>,可以通过命令mvn clean test在执行测试用例的时候就把覆盖率报告生成到coverage_reports目录下,该目录可以根据需要进行修改。

3.2.3 覆盖率100%

作为开发人员,覆盖率就应该追求覆盖率100%。在制度上也应该这样设定,这样比较容易监督。实在无法测试或者没有必要测试的则可以排除掉,排除的类也可以定期进行检查,看看是否真的符合排除的条件。这个需要在工具上能够检测,使用mvn jacoco:check命令进行检测:

<plugin><groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artifactId><version>0.8.13</version><configuration><excludes><exclude>com/qqian/stepfmk/srvpro/SrvproApplication.class</exclude></excludes><rules><rule><element>PACKAGE</element><limits><limit><counter>LINE</counter><value>COVEREDRATIO</value><minimum>1</minimum></limit></limits></rule></rules></configuration><executions><execution><id>prepare-agent</id><goals><goal>prepare-agent</goal></goals></execution><execution><id>report</id><phase>test</phase><goals><goal>report</goal></goals><configuration><outputDirectory>${project.build.directory/}coverage_reports</outputDirectory></configuration></execution><execution><id>check</id><phase>verify</phase><goals><goal>check</goal></goals></execution></executions>
</plugin>

上面配置中增加了check的<execution>节点,同时在这个插件的根里增加了配置:

1、排除掉一部分无法测试的类(可以用*、**来模糊匹配),如springboo的启动类没有必要进行测试;

2、增加<rules>节点指定按行(LINE)检查覆盖率,要达到100%。规则的配置可以参考:https://www.jacoco.org/jacoco/trunk/doc/check-mojo.html

3.2.4 黑盒测试覆盖率

公司一般还有专门的测试部门,他们做的主要是黑盒测试。Jacoco也支持在java程序在运行的过程中收集测试覆盖率信息,这样就可以了解到黑盒测试到底覆盖了哪些代码,哪些没有被覆盖到。

在启动Java程序的时候,增加一个agent服务器,用于后面dump测试覆盖率的report:

java -jar srvpro-1.0.0-SNAPSHOT.jar -javaagent:jacocoagent.jar=excludes=com/qqian/stepfmk/srvpro/SrvproApplication.class,output=tcpserver,address=127.0.0.1,port=6300

-javaagent:jacocoagent.jar的格式为:-javaagent:[yourpath/]jacocoagent.jar=[option1]=[value1],[option2]=[value2],即其value是一个key-value对形式,用逗号分隔,key和value用等号分隔。更详细可参考:https://www.eclemma.org/jacoco/trunk/doc/agent.html

jacocoagent.jar包下载:https://www.eclemma.org/jacoco/index.html

执行测试后,需要用cli命令先dump出数据,然后用report命令把数据转为hmtl文件才可以看:参考https://www.jacoco.org/jacoco/trunk/doc/cli.html

# dump数据
java -jar jacococli.jar dump [--address <address>] --destfile <path> [--help] [--port <port>] [--quiet] [--reset] [--retry <count>]
例子:java -jar jacococli.jar dump --address 127.0.0.1 --port 6300 --destfile /path/jacoco.exec# 转成report
java -jar jacococli.jar report [<execfiles> ...] --classfiles <path> [--csv <file>] [--encoding <charset>] [--help] [--html <dir>] [--name <name>] [--quiet] [--sourcefiles <path>] [--tabwith <n>] [--xml <file>]
例子:java -jar jacococli.jar report /path/jacoco.exec

4 架构一小步

1、通过spring-boot-starter-test引入测试库junit、断言库assertj、mock库mockito;

2、规范:把单元测试放到比较重要的位置,测试覆盖率要达100%;

3、规范:单元测试代码只做mock对象、测试业务逻辑、断言三件事,测试代码要保持简单,不能有业务逻辑。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/88906.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/88906.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/88906.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 文件共享之 HGFS 共享配置全解析

一、前言在使用 VMware 虚拟机搭建 Linux&#xff08;以 Ubuntu 为例&#xff09;环境时&#xff0c;常常需要实现主机与虚拟机之间的文件共享&#xff0c;HGFS&#xff08;VMware Host-Guest File System&#xff09;就是一种常用的文件共享方式。通过它&#xff0c;我们可以方…

模块化设计赋能:定制组装锂电池设备的柔性生产解决方案

在锂电池行业快速迭代的背景下&#xff0c;定制化需求与规模化生产之间的矛盾日益凸显。传统锂电池组装设备采用固定式架构&#xff0c;功能模块高度耦合&#xff0c;导致设备换型周期长、兼容性差&#xff0c;难以适应电芯规格频繁变化、工艺路线持续升级的市场需求。模块化设…

Kubernetes 架构原理与集群环境部署

一&#xff1a;为什么需要 Kubernetes在业务开始进行容器化时&#xff0c;前期需要容器化的项目可能并不多&#xff0c;涉及的容器也并不多&#xff0c;此时基于 Docker 容器直接部署至宿主机也能实现基本的需求。但是随着项目越来越多&#xff0c;管理的容器也会越来越多&…

JavaScript中关于环境对象的拓展

1.环境对象的定义环境对象指的是函数内的特殊变量this&#xff0c;this指向函数的调用者它代表当前函数的运行环境在平常我们判断this经常用口诀谁调用它&#xff0c;它就指向谁&#xff0c;以下是几种常见情况1. 在全局作用域中&#xff0c;this指向window2.在函数中&#xff…

202507中央城市工作会议

国家终于要给城市"升级系统"了&#xff01;未来城市不再拼命盖新楼&#xff0c;而是让现有城区更安全、舒适、智能&#xff0c;且每个城市都要找到自己的特色发展路径 2025年7月北京“中央城市工作会议”。领导人聚在一起&#xff0c;讨论“怎么把中国城市搞得更好”…

springboot如何redis锁

如何解决超卖问题?超卖问题&#xff1a;就是多个线程并发执行&#xff0c;目前唯一方案是加锁。如图&#xff1a;悲观锁其实还有数据库的互斥锁。悲观锁是最常见的乐观锁实现的原理&#xff1a;版本号&#xff1a;这种方案就是&#xff1a;扣款库存的时候首先先查询版本号&…

minio批量删除对象不生效

下午在写minio上批量删除对象的逻辑&#xff0c;各种改对象名称&#xff0c;各种核对代码&#xff0c;发现啥都没错&#xff0c;但是删除就是不生效。 代码如下&#xff1a; from minio.deleteobjects import DeleteObjectdelete_object_list [DeleteObject("20250626/20…

如何设计实现开发自助重启工具-01-设计篇

自助重启系列 如何设计实现开发自助重启工具-01-设计篇 应用部署作业-02-流程 如何实现自助重启-03-实现篇 开发自助重启 说明&#xff1a;有时候研发产线需要重启&#xff0c;为了保证安全、或者说提升效率&#xff0c;最好有一个统一的研发自助重启页面。 这个功能可应…

ChatTongyi × LangChain:开启多模态AI应用创新之门

阿里云通义实验室推出的ChatTongyi&#xff08;基于通义千问大模型&#xff09;与LangChain框架的深度集成&#xff0c;为开发者打造了一套高效、灵活、全面的AI开发工具链。无论是文本对话、复杂任务自动化&#xff0c;还是图像理解&#xff0c;这一组合都为多场景智能应用的落…

Android Studio C++/JNI/Kotlin 示例 二

MainActivity.ktpackage com.demo.learn1import android.os.Bundle import android.util.Log import androidx.activity.ComponentActivityclass MainActivity : ComponentActivity() {// 加载原生库init {System.loadLibrary("native_code")}// 声明原生方法// 数学…

B树和B+树

B树B树&#xff0c;⼜称多路平衡查找树&#xff0c;B树中所被允许的孩⼦个数的最⼤值称为B树的阶&#xff0c;通常⽤m表示。⼀棵m阶B树或为空树&#xff0c;或为满⾜如下特性的m叉树&#xff1a; 1&#xff09;树中每个结点⾄多有m棵⼦树&#xff0c;即⾄多含有m-1个关键字。 2…

【版本控制】Perforce Helix Core (P4V) 完全入门指南(含虚幻引擎实战)

目录引言第一章&#xff1a;认识 Perforce Helix Core1.1 什么是 Perforce&#xff1f;1.2 P4V 是什么&#xff1f;1.3 核心概念速览1.4 为什么选择 Perforce&#xff1f;1.5 与 Git 的核心区别本章总结第二章&#xff1a;安装与配置2.1 安装原则&#xff1a;先服务端后客户端2…

LlamaFactory/unsloth Demo

内部叫Tuning-Factory 参数文档https://llamafactory.readthedocs.io/zh-cn/latest/index.html 高级技巧&#xff0c;如加速&#xff1a;https://llamafactory.readthedocs.io/zh-cn/latest/advanced/acceleration.html 0.环境 conda env list conda remove --name llm --all c…

水务工程中自动化应用:EtherNet/IP转PROFIBUS DP连接超声波流量计

在水务工程领域&#xff0c;自动化技术的应用愈发广泛。随着工业4.0概念的普及&#xff0c;不同通信协议的设备之间实现高效互联互通变得尤为关键。EtherNet/IP和PROFIBUS DP作为两种常见的工业通信协议&#xff0c;各有优势&#xff0c;在实际应用中&#xff0c;常需要将它们进…

网络协议和基础通信原理

网络协议和基础通信原理是理解互联网和各种网络应用的关键。让我用通俗易懂的方式&#xff0c;带你逐一深入讲解这些内容。 一、基础概念总览 TCP/IP协议族&#xff1a;互联网通信的基础&#xff0c;由一组协议组成&#xff0c;包括TCP、IP、UDP等。HTTP协议&#xff1a;基于T…

T16IZ遥控器教程__遥控器与无人机对频

文章目录前言一、准备设备二、对频步骤总结前言 在使用自组PX4无人机时&#xff0c;有的小伙伴可能会遇到遥控器无法与无人机对频连接的问题&#xff0c;别担心&#xff0c;这篇文章会解决它。 一、准备设备 如下图&#xff0c;无人机信号接收器&#xff0c;与无人机。 遥控器…

pyspark中map算子和flatmap算子

在 PySpark 中&#xff0c;map 和 flatMap 是两个常用的转换算子&#xff0c;它们都用于对 RDD&#xff08;弹性分布式数据集&#xff09;或 DataFrame 中的元素进行处理&#xff0c;但处理方式和应用场景有所不同。下面详细讲解它们的用法和适用场景。1. map 算子功能对 RDD 或…

jenkins部署前端vue项目使用Docker+Jenkinsfile方式

文章目录前言一、前提准备二、准备构建文件三、Jenkins中构建项目总结前言 前面通过jenkinsdocker的方式部署了若依前端vue项目&#xff0c;接下来接着学习使用Jenkinsfile的方式部署前端vue项目。 一、前提准备 已经安装好centos服务器&#xff0c;并且安装了jenkins和docke…

Cadence操作说明

一.allegro修改丝印字体大小的方法 1.选择Edit–>Change&#xff0c;右侧弹出Options选项&#xff0c;选择Class : New subclass Ref Des : Silkscreen_Top&#xff0c;设置Text block&#xff0c;后面的数字代表字号的大小。菜单菜单栏选择Setup–>Design Parameters&a…

使用Stitch来生成CrypyTrack的app程序

结果&#xff1a; &#x1f9ed; 第一步&#xff1a;访问 Stitch 平台 打开网址&#xff1a;stitch.withgoogle.com使用你的 Google 账号登录&#xff0c;无需安装任何软件 &#x1f9f1; 第二步&#xff1a;选择设计模式 Stitch 提供两种模式&#xff1a; 标准模式&#xf…