Java 单元测试最佳实践:如何充分利用测试自动化
单元测试是众所周知的做法,但还有很大的改进空间!在这篇文章中,我们讨论最有效的单元测试最佳实践,包括在此过程中最大化自动化工具的方法。我们还将讨论代码覆盖率、模拟依赖关系和整体测试策略。
什么是单元测试?
单元测试是测试应用程序的各个单元或组件的做法,以验证每个单元是否正常工作。一般来说,一个单元应该是应用程序的一小部分——在 Java 中,它通常是一个类。请注意,我在这里并没有严格定义“单元”,而是由开发人员决定每个测试的测试代码的范围。
人们有时会将术语“单元测试”与“集成测试”或“端到端测试”进行对比。区别在于,通常,单元测试是为了验证单个可测试单元的行为,而集成测试是验证多个组件一起或整个应用程序的行为。正如我所说,“单元”的构成并没有严格定义,每个测试的范围由您决定。
为什么要进行单元测试?
单元测试是一种经过验证的确保软件质量的技术,具有很多好处。以下是进行单元测试的几个重要原因:
单元测试验证您的每个软件不仅现在可以正常工作,而且在未来也可以继续工作,为未来的开发提供坚实的基础。
单元测试可以在生产过程的早期阶段识别缺陷,从而降低在开发周期后期修复这些缺陷的成本。
经过单元测试的代码通常重构起来更安全,因为可以快速重新运行测试以验证行为没有改变。
编写单元测试迫使开发人员考虑生产代码的设计如何,以使其适合单元测试,并使开发人员从不同的角度看待他们的代码,鼓励他们在实现中考虑极端情况和错误情况。
在代码审查过程中包括单元测试可以揭示修改后的或新的代码应该如何工作。另外,审阅者可以确认测试是否良好。
不幸的是,很多时候,开发人员要么根本不编写单元测试,要么不编写足够的测试,要么不维护它们。我理解——单元测试有时编写起来很棘手,或者维护起来很耗时。有时需要满足最后期限,感觉编写测试会让我们错过那个最后期限。但是,没有编写足够的单元测试或没有编写良好的单元测试是一个很容易陷入的危险陷阱。
因此,请考虑我以下关于如何编写干净、可维护、自动化测试的最佳实践建议,这些测试可以让您以最少的时间和精力享受单元测试的所有好处。
单元测试最佳实践
让我们看一下构建、运行和维护单元测试的一些最佳实践,以获得最佳结果。
单元测试应该值得信赖
如果代码被破坏并且仅当代码被破坏时测试必定失败。如果不是,我们就不能相信测试结果告诉我们的内容。
单元测试应该是可维护和可读的
当生产代码发生变化时,测试通常需要更新,也可能需要调试。因此,测试必须易于阅读和理解,不仅对于编写测试的人来说,而且对于其他开发人员来说也是如此。始终为了清晰和可读性而组织和命名您的测试。
单元测试应该验证单个用例
好的测试只能验证一件事,而且只能验证一件事,这意味着它们通常会验证单个用例。遵循此最佳实践的测试更简单且更易于理解,这有利于可维护性和调试。验证不止一件事的测试很容易变得复杂且维护起来耗时。不要让这种事发生。
另一个最佳实践是使用最少数量的断言。有些人建议每个测试只使用一个断言(这可能有点过于严格);这个想法是专注于仅验证您正在测试的用例所需的内容。
单元测试应该隔离
测试应该可以在任何机器上以任何顺序运行,而不会相互影响。如果可能,测试不应依赖于环境因素或全局/外部状态。具有这些依赖项的测试更难运行并且通常不稳定,这使得它们更难调试和修复,并且最终花费的时间比节省的时间更多(请参阅上面的trustworthy)。
几年前,Martin Fowler撰写了有关 “孤独”与“社交”代码的文章,以描述应用程序代码中的依赖项使用情况,以及如何相应地设计测试。在他的文章中,“独立”代码不依赖于其他单元(它更加独立),而“社交”代码确实与其他组件交互。如果应用程序代码是孤独的,那么测试很简单,但对于被测试的社交代码,您可以构建“孤独”或“社交”测试。“社交测试”将依赖于真实的依赖关系来验证行为,而“单独测试”则将被测代码与依赖关系隔离开来。您可以使用模拟来隔离被测代码,并为“社交”代码构建“单独”测试。我们将在下面看看如何做到这一点。
一般来说,使用模拟来处理依赖关系使我们作为测试人员的生活更轻松,因为我们可以为社交代码生成“单独的测试”。对复杂代码的社交测试可能需要大量设置,并且可能违反隔离和可重复的原则。但由于模拟是在测试中创建和配置的,因此它是独立的,我们可以更好地控制依赖项的行为。另外,我们可以测试更多代码路径。例如,我可以返回自定义值或从模拟中抛出异常,以覆盖边界或错误条件。
单元测试应该自动化
确保测试在自动化过程中运行。这可以是每天,也可以是每小时,也可以是在持续集成或交付过程中。团队中的每个人都需要能够访问和审查这些报告。作为一个团队,讨论您关心哪些指标:代码覆盖率、修改后的代码覆盖率、正在运行的测试数量、性能等。
通过查看这些数字可以学到很多东西,这些数字的大幅变化通常表明可以立即解决回归问题。
单元测试应验证所有细节、极端情况和边界条件等。应更加谨慎地使用组件、集成、UI 和功能测试,以验证 API 或应用程序作为一个整体的行为。手动测试应该占整个金字塔结构的最小百分比,但对于发布验收和探索性测试仍然有用。该模型为组织提供了高水平的自动化和测试覆盖率,以便他们可以扩大测试工作并将与构建、运行和维护测试相关的成本保持在最低水平。
单元测试应在有组织的测试实践中执行
为了推动各级测试的成功,并使单元测试过程可扩展且可持续,您将需要一些额外的实践。首先,这意味着在编写应用程序代码时编写单元测试。一些组织在应用程序代码之前编写测试(测试驱动或行为驱动编程)。重要的是测试与应用程序代码齐头并进。测试和应用程序代码甚至应该在代码审查过程中一起审查。评论可以帮助您理解正在编写的代码(因为它们可以看到预期的行为)并改进测试!
相关文章:
Java 单元测试最佳实践:如何充分利用测试自动化
单元测试是众所周知的做法,但还有很大的改进空间!在这篇文章中,我们讨论最有效的单元测试最佳实践,包括在此过程中最大化自动化工具的方法。我们还将讨论代码覆盖率、模拟依赖关系和整体测试策略。 什么是单元测试? 单…...
windows系统用于 SDN 的软件负载均衡器 (SLB)
适用于:Azure Stack HCI 版本 22H2 和 21H2;Windows Server 2022、Windows Server 2019、Windows Server 2016 软件负载均衡器包括哪些内容? 软件负载均衡器提供以下功能: 适用于北/南和东/西 TCP/UDP 流量的第 4 层 (L4) 负载均…...
漏洞复现--IP-guard flexpaper RCE
免责声明: 文章中涉及的漏洞均已修复,敏感信息均已做打码处理,文章仅做经验分享用途,切勿当真,未授权的攻击属于非法行为!文章中敏感信息均已做多层打马处理。传播、利用本文章所提供的信息而造成的任何直…...
Electron-vue出现GET http://localhost:9080/__webpack_hmr net::ERR_ABORTED解决方案
GET http://localhost:9080/__webpack_hmr net::ERR_ABORTED解决方案 使用版本解决方案解决总结 使用版本 以下是我解决此问题时使用的electron和vue等的一些版本信息 【附】经过测试 electron 的版本为 13.1.4 时也能解决 解决方案 将项目下的 .electron-vue/dev-runner.js…...
Linux---(六)自动化构建工具 make/Makefile
文章目录 一、make/Makefile二、快速查看(1)建立Makefile文件(2)编辑Makefile文件(3)解释(4)效果展示 三、背后的基本知识、原理(1)如何清理对应的临时文件呢…...
谷歌:编写干净的代码以减少认知负荷
您是否曾经阅读过代码却发现很难理解?您可能正在经历认知负荷! 认知负荷是指完成一项任务所需的脑力劳动量。阅读代码时,您必须记住变量值、条件逻辑、循环索引、数据结构状态和接口契约等信息。随着代码变得更加复杂,认知负荷也…...
微信小程序display常用属性和子元素排列方式介绍
wxss中display常用显示属性与css一致,介绍如下: 针对元素本身显示的属性: displayblock,元素显示换行displayinline,元素显示换行,但不可设置固定的宽度和高度,也不可设置上下方向的margin和p…...
设计模式—结构型模式之代理模式
设计模式—结构型模式之代理模式 代理模式(Proxy Pattern) ,给某一个对象提供一个代理,并由代理对象控制对原对象的引用,对象结构型模式。 静态代理 比如我们有一个直播平台,提供了直播功能,但是如果不进行美颜,可能就比较冷清…...
C# PDF转HTML字符串
需要nuget安装Aspose.PDF插件,本文使用23.10.0版本 一、获取PDF文件,保存到某个路径;再读取返回字符串。 //html文件保存路径 string filePath dirPath "xxx.html"; if (!File.Exists(filePath)) {//获取pdf文件流Byte[] pdfBy…...
el-table解决数据过少小于高度有留白的问题
问题:给el-table设置个高度,高度为500px,之后就添加如下4条数据,那么底部就没数据,直接就空白了,本文章就是为了解决这个问题,如果底部留白那么就添加几条空数据就行了.如果数据已达到高度了那么就不会留白了 1.效果 这个空列可以根据高度来决定添加几个空格子去铺满列表&…...
vue实现无感刷新token
vue实现无感刷新token 1、前言2、实现思路2.1 方法一2.2 方法二2.3 方法三 3、可能遇到的问题3.1 问题一:如何防止多次刷新token3.2 问题二:同时发起两个或者两个以上的请求时,其他接口怎么解决 1、前言 最近在做vue3管理系统项目的时候&…...
竞赛选题 深度学习的动物识别
文章目录 0 前言1 背景2 算法原理2.1 动物识别方法概况2.2 常用的网络模型2.2.1 B-CNN2.2.2 SSD 3 SSD动物目标检测流程4 实现效果5 部分相关代码5.1 数据预处理5.2 构建卷积神经网络5.3 tensorflow计算图可视化5.4 网络模型训练5.5 对猫狗图像进行2分类 6 最后 0 前言 &#…...
Python高级语法----Python C扩展与性能优化
文章目录 1. 编写Python C扩展模块示例代码编译和运行运行结果2. 利用Cython优化性能示例代码编译和运行运行结果3. Python性能分析工具示例代码分析结果1. 编写Python C扩展模块 Python C扩展模块允许你将C语言代码集成到Python程序中,以提高性能。这对于计算密集型任务特别…...
行业洞察:分布式云如何助力媒体与娱乐业实现创新与增长?
过去数年,流媒体经历了蓬勃的发展过程,观众可以根据喜好收看自己所喜爱的节目内容,并希望在全球范围内访问内容。 繁荣的市场让媒体和娱乐行业的 IT 领导者们竞相发力,用更短的时间去创造互动且令人难忘的内容体验,力求…...
【多线程 - 05、后台线程】
后台线程 后台线程,它是在后台运行的,它的任务是为其他线程提供服务,这种线程被称为“后台线程(Daemon Thread)”,又称为“守护线程”或“精灵线程”。JVM的垃圾回收线程就是典型的后台线程。 后台线程的特…...
C语言之文件操作(剩余部分)
上篇博客字数到极限了,给大家把内容补充在这一篇,我们还剩下文件读取结束的判定和文件缓冲区的内容没有介绍,让我们开始下面的学习吧! 目录 1.文件读取结束的判定 1.1feof函数 1.2ferror函数 代码示例 2.文件缓冲区 2.1fflu…...
【PC】开发者日志:竞技比赛验证系统强化
各位玩家大家好!欢迎收看本期开发者日志。 在11月1日发布的第26赛季第2轮更新公告中,我们提到了有关强化比赛验证系统的内容。想必各位玩家一定会对我们加强验证系统的背景和意图感到好奇,为此我们想通过今天这篇反作弊开发者日志来向大家更详…...
c++用map,创建类似于python中的字典
1.创建 #include <map> #include <string> #include <iostream>using namespace std; int main() {/*using std::map;using std::string;using std::cout;*/map<string, string> myMap1 {{"Name", "ClearLove"},{"Gender&q…...
VuePress介绍及使用指南
VuePress是一个基于Vue.js的静态网站生成工具,它专注于以Markdown为中心的项目文档。VuePress具有简单易用的特性,同时提供了强大的自定义和扩展性。在本文中,我们将介绍VuePress的基本概念,并提供一个简单的使用指南。 什么是Vue…...
Spring-Security前后端分离权限认证
前后端分离 一般来说,我们用SpringSecurity默认的话是前后端整在一起的,比如thymeleaf或者Freemarker,SpringSecurity还自带login登录页,还让你配置登出页,错误页。 但是现在前后端分离才是正道,前后端分离的话,那就…...
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?
Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以? 在 Golang 的面试中,map 类型的使用是一个常见的考点,其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...
大数据学习(132)-HIve数据分析
🍋🍋大数据学习🍋🍋 🔥系列专栏: 👑哲学语录: 用力所能及,改变世界。 💖如果觉得博主的文章还不错的话,请点赞👍收藏⭐️留言Ǵ…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
