【编码心得】单元测试的那些事

news2024/9/22 19:43:15

【编码心得】单元测试的那些事

文章目录

  • 单元测试定义?
  • 为什么需要单元测试?
      • 为重构保驾护航
      • 提高代码质量
      • 减少 bug
      • 快速定位 bug
      • 持续集成依赖单元测试
      • 团队编码规范要求
      • 大牛都写单元测试
      • 保住面子
  • TDD 测试驱动开发
      • 何谓 TDD?
      • TDD的基本流程
      • TDD 优缺点分析
  • 单测框架如何选择?
      • 一、选择标准
      • 二、推荐的Java单测框架
      • 三、选择建议
  • AI时代下的单元测试
  • 总结

单元测试定义?

单元测试是指对软件中的最小可测试单元(如函数、方法、类等)进行隔离测试的过程。这些单元在测试过程中被单独运行,以确保它们的行为符合预期。单元测试是软件开发中最低级别的测试活动,旨在发现模块内部存在的各种错误。

在做单元测试时,为了隔离外部依赖,确保这些依赖不影响验证逻辑,我们经常会用到 Fake、Stub 与 Mock 。
在这里插入图片描述

关于 Fake、Mock 与 Stub 这几个概念的详细解析:

1. Fakes(伪对象)
定义: Fakes是那些包含了生产环境下具体实现的简化版本的对象。它们不是完整的生产实现,但会采取一些捷径,拥有生产代码的简化版本。
特点: Fakes关注于核心逻辑,去除多余的内容。例如,在测试过程中,可能不需要真实的数据库操作,而Fakes则可以通过内存中的数据结构来模拟数据库操作,从而简化测试步骤。
Fakes可以用于原型设计或峰值模拟中,以快速实现系统原型并基于内存存储来运行整个系统。
另一个常见的使用场景是利用Fakes来保证在测试环境下支付、邮件发送等操作永远返回成功结果,以避免外部依赖对测试的影响。
2. Mocks(模拟对象)
定义: Mocks是一种特殊的测试双体,它们允许测试者定义对象的行为并验证这些行为是否被调用。Mocks可以模拟对象的方法调用、返回值以及异常等。
特点: Mocks能够使得测试失败,这意味着它们可以人为地制造一些异常或特定条件来验证程序对这些异常或条件的处理方式是否如预期。
Mocks更适合于测试那些具有复杂依赖或外部交互的功能,如发送邮件、访问数据库等。
通过Mocks,测试者可以确保在测试过程中不会受到外部系统或依赖的干扰,从而专注于测试目标本身。
3. Stubs(存根对象)
定义: Stubs是那些包含了预定义好的数据并且在测试时返回给调用者的对象。它们通常用于替代那些难以控制或需要复杂设置的依赖。
特点: Stubs关注于输入输出,即它们会伪造一个输入并返回一个预期的输出,以验证被测方法的正确性。
Stubs常用于查询(Query)方法的测试中,这些方法通常只返回数据而不改变系统状态。
通过Stubs,测试者可以简化测试用例的编写,无需担心外部依赖的复杂性和不确定性。

为什么需要单元测试?

为重构保驾护航

单元测试可以为重构提供信心,降低重构的成本。我们要像重视生产代码那样,重视单元测试。
每个开发者都会经历重构,重构后把代码改坏了的情况并不少见,很可能你只是修改了一个很简单的方法就导致系统出现了一个比较严重的错误。

提高代码质量

由于每个单元有独立的逻辑,做单元测试时需要隔离外部依赖,确保这些依赖不影响验证逻辑。因为要把各种依赖分离,单元测试会促进工程进行组件拆分,整理工程依赖关系,更大程度减少代码耦合。这样写出来的代码,更好维护,更好扩展,从而提高代码质量。

减少 bug

一个可单元测试的工程,会把业务、功能分割成规模更小、有独立的逻辑部件,称为单元。单元测试的目标,就是保证各个单元的逻辑正确性。单元测试保障工程各个“零件”按“规格”(需求)执行,从而保证整个“机器”(项目)运行正确,最大限度减少 bug。

快速定位 bug

如果程序有 bug,我们运行一次全部单元测试,找到不通过的测试,可以很快地定位对应的执行代码。修复代码后,运行对应的单元测试;如还不通过,继续修改,运行测试……直到测试通过。

持续集成依赖单元测试

持续集成需要依赖单元测试,当持续集成服务自动构建新代码之后,会自动运行单元测试来发现代码错误。

团队编码规范要求

有些经验丰富的领导,或多或少都会要求团队写单元测试。对于有一定工作经验的队友,这要求挺合理

大牛都写单元测试

大牛的自我修养,膜拜学习,坚持写高质量单测
在这里插入图片描述

保住面子

都是有些许年经验的老鸟,还天天被测试同学追 bug,好意思么?花多一点时间写单元测试,确保没低级 bug,也怕别人不小心改了自己的代码,新版本上线提心吊胆……花点时间写单元测试,有事没事跑一下测试,确保原逻辑没问题,至少能睡安稳一点。

TDD 测试驱动开发

何谓 TDD?

TDD(Test Driven Development,测试驱动开发)是敏捷开发中的一项核心实践和技术,也是一种设计方法论。其核心思想是在编写实际代码之前先编写测试代码,然后根据测试代码来驱动实际代码的编写。以下是对TDD的详细解释:

TDD的基本流程

TDD的基本流程通常包括以下几个步骤:

  • 编写测试案例:首先,根据需求编写测试案例,测试案例通常包括输入数据、预期输出以及测试方法。
  • 运行测试案例:运行编写的测试案例,此时测试案例会失败,因为还没有编写代码来满足测试需求。
  • 编写最小量代码:根据测试案例编写最小量代码以使测试通过。
  • 再次运行测试案例:确保新编写的代码能够通过所有的测试案例。
  • 重构代码:对代码进行重构,保持代码质量,消除冗余,提高可读性。

这个过程是一个迭代的过程,不断重复“编写测试案例—编写代码—运行测试—重构代码”的步骤,直到完成所有功能的开发。

TDD 优缺点分析

测试驱动开发有好处也有坏处。因为每个测试用例都是根据需求来的,或者说把一个大需求分解成若干小需求编写测试用例,所以测试用例写出来后,开发者写的执行代码,必须满足测试用例。如果测试不通过,则修改执行代码,直到测试用例通过。

优点:

  • 帮你整理需求,梳理思路;
  • 帮你设计出更合理的接口(空想的话很容易设计出屎);
  • 减小代码出现 bug 的概率;
  • 提高开发效率(前提是正确且熟练使用 TDD)。

缺点:

  • 能用好 TDD 的人非常少,看似简单,实则门槛很高;
  • 投入开发资源(时间和精力)通常会更多;
  • 由于测试用例在未进行代码设计前写;很有可能限制开发者对代码整体设计;
  • 可能引起开发人员不满情绪,我觉得这点很严重

单测框架如何选择?

以下是一些关键的选择标准和推荐的Java单测框架:

一、选择标准

兼容性:
确保所选框架与Java版本及项目依赖库兼容。
社区支持:
活跃的社区意味着有更多的文档、教程和问题解决方案。
易用性:
框架的学习曲线应平缓,易于上手,同时提供清晰的错误信息和调试支持。
扩展性:
支持自定义测试用例、测试套件和插件,以满足不同的测试需求。
集成能力:
能够与持续集成(CI)工具、IDE和其他开发工具无缝集成。
功能特性:
提供丰富的断言方法、测试运行器、数据驱动测试等特性。

二、推荐的Java单测框架

JUnit
简介: JUnit是Java编程语言中最常用的单元测试框架之一。它提供了一个简单的框架来编写和运行可重复的测试。
特点: 丰富的断言方法,如assertEquals、assertNotNull等。
支持测试套件和测试运行器。易于与IDE和构建工具集成。
适用场景: 适用于大多数Java项目的单元测试。

TestNG
简介:TestNG是JUnit的一个替代品,它提供了更丰富的测试用例定义和配置方式。
特点: 支持测试套件、数据驱动测试、依赖测试、并行测试等高级特性。使用XML文件进行配置,支持复杂的测试场景。提供多种测试运行器和扩展插件。
适用场景: 适用于需要复杂测试场景和高级特性的项目。

Mockito
简介: 虽然Mockito本身不是一个完整的单元测试框架,但它是一个流行的Mocking框架,经常与JUnit等框架结合使用。
特点: 允许开发者创建和配置Mock对象,以模拟外部依赖的行为。提供丰富的API来定义Mock对象的行为和验证它们的交互。易于与JUnit等框架集成。
适用场景: 适用于需要Mock外部依赖以进行隔离测试的场景。

三、选择建议

根据项目需求选择: 根据项目的具体需求和团队的实际情况选择合适的框架。例如,如果项目需要复杂的测试场景和高级特性,可以考虑使用TestNG;如果项目主要关注单元测试,并且需要Mock外部依赖,那么JUnit结合Mockito可能是一个不错的选择。

考虑社区支持: 选择拥有活跃社区和广泛用户基础的框架,以便在遇到问题时能够获得及时的帮助和支持。

评估学习成本: 考虑团队成员对所选框架的熟悉程度和学习成本,选择易于上手且能够快速提高测试效率的框架。

集成与扩展性: 确保所选框架能够与现有的开发工具和流程无缝集成,并支持未来的扩展需求。

AI时代下的单元测试

现在生成式AI的爆火,着实让UT的编写爽翻了,你敢想象:一个复杂service的单元测试的编写,只需要告诉ai:“帮我生成单元测试”,噼里啪啦生成了一堆单测,然后定睛一瞅,我去,还写得挺不赖,稍作修改就能使用! 科技发展提高生产力~~yyds

在这里插入图片描述

总结

单元测试确实会带给你相当多的好处,但不是立刻体验出来。写了可以买个放心,对代码的一种保障,有 bug 尽快测出来,以下是个人对单元测试一些建议:

  1. 遵循测试金字塔
    测试金字塔是一个指导原则,它建议我们在项目中拥有不同级别的测试,但每种类型的测试数量应该有所不同。单元测试应该位于金字塔的底部,数量最多,因为它们运行速度快且容易编写。集成测试位于中间,而端到端测试(或系统测试)则位于顶部,数量较少。
  2. 保持测试的简洁性
    每个单元测试都应该专注于测试一个小的、具体的功能点。避免在单个测试中测试多个逻辑路径或方法。如果测试变得复杂,考虑将其拆分成多个更小的测试。
  3. 编写可重复的测试
    确保你的测试不依赖于外部状态或数据(如数据库、文件系统或网络状态)。使用mocking框架(如Mockito)来模拟依赖项,以便测试能够独立于这些外部因素运行。
  4. 使用断言来验证结果
    断言是单元测试的核心。使用断言来明确验证你的代码是否按预期工作。JUnit 5提供了丰富的断言库,你可以使用这些断言来检查返回值、异常、集合内容等。
  5. 编写有意义的测试名称
    测试方法的名称应该清晰地描述它们所测试的内容。避免使用模糊的名称,如test1()、testMethod()等。相反,使用像testAddTwoNumbers()、testUserCreationWithInvalidEmailThrowsException()这样的名称。
  6. 遵循测试驱动开发(TDD)
    虽然TDD不是强制性的,但它是一种强大的实践,可以帮助你编写更清晰、更可维护的代码。TDD鼓励你先写测试,然后编写使测试通过的代码。这有助于你专注于当前正在实现的功能,并确保代码始终符合其预期用途。
  7. 关注代码覆盖率,但不要过度
    代码覆盖率是衡量测试质量的一个重要指标,但它并不是唯一的指标。确保你的测试覆盖了关键路径和边界条件,但也要避免编写无用的测试,这些测试只是为了提高覆盖率而编写的。
  8. 自动化测试运行
    将单元测试集成到你的构建流程中,以便在每次提交代码时自动运行测试。这有助于快速发现问题,并确保新代码不会破坏现有功能。
  9. 审查和重构测试代码
    与应用程序代码一样,测试代码也需要进行审查和重构。随着应用程序的发展,测试代码可能会变得过时或冗余。定期审查和重构测试代码可以帮助你保持其质量和可维护性。
  10. 编写可读的测试代码
    与应用程序代码一样,测试代码也应该易于阅读和理解。使用清晰的命名、注释和结构化代码来提高可读性。这将使其他开发者(或未来的你)更容易理解和维护测试代码。
  11. 越重要的代码,越要写单元测试;
    代码做不到单元测试,多思考如何改进,而不是放弃;边写业务代码,边写单元测试,而不是完成整个新功能后再写;多思考如何改进、简化测试代码。测试代码需要随着生产代码的演进而重构或者修改,如果测试不能保持整洁,只会越来越难修改。
    在这里插入图片描述

我是杰叔叔,一名沪漂的码农,下期再会!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

全球轻型汽车市场规划预测:2030年市场规模将接近2502亿元,未来六年CAGR为2.8%

一、引言 随着全球经济的发展和消费者出行需求的增加,轻型汽车作为汽车市场中的重要组成部分,其市场重要性日益凸显。本文旨在探索轻型汽车行业的发展趋势、潜在商机及其未来展望。 二、市场趋势 全球轻型汽车市场的增长主要受全球经济发展、消费者对出…

海风小店微信商城小程序附后端一款免费开源的小程序源码

该商城小程序服务端api基于node.jsThinkJSMySQL,如果对这个不大熟悉的人, 可能有那么一点难度,但是如果只是搭建的话,作者的教程还是比较详细的,而且搭建步骤比较简单, 应该很容易上手,如果你…

【KAN】【API教程】索引

简单来说就是确定激活函数的坐标 from kan import *model = KAN(width=[2,3,2,1]) x = torch.normal(0,1,size=(100,2)) model(x); beta = 100 model.plot(beta=beta) # [2,3,2,1] means 2 input nodes # 3 neurons in the first hidden layer, # 2 neurons in the second hid…

知识图谱开启了一个可以理解的人工智能未来

概述 本文是对利用知识图谱(KG)的综合人工智能(CAI)的全面调查研究,其中 CAI 被定义为可解释人工智能(XAI)和可解释机器学习(IML)的超集。 首先,本文澄清了…

【Linux学习】实现一个简单版的Shell

🍑个人主页:Jupiter. 🚀 所属专栏:Linux从入门到进阶 欢迎大家点赞收藏评论😊 目录 📕前言🍑shell📚Shell的工作原理🔒Shell的高级功能 🚀shell的代码实现&am…

Mybatis实战:#{} 和 ${}的使用区别和数据库连接池

一.#{} 和 ${} #{} 和 ${} 在MyBatis框架中都是用于SQL语句中参数替换的标记,但它们在使用方式和处理参数值上存在一些显著的区别。 #{}的作用: #{} 是MyBatis中用于预编译SQL语句的参数占位符。它会将参数值放入一个预编译的PreparedStatement中&am…

JavaScript ES6语法详解(下)

前言:哈喽,大家好,我是码喽的自我修养!今天给大家分享JavaScript ES6语法详解(下)!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到带大家,欢迎收藏关注…

信创企业级即时通讯发展趋势,私有化安全沟通

信创(创新型科技公司)在当今的商业环境中发挥着重要作用,因此,他们对于私有化安全沟通的需求日益增加。企业级即时通讯软件是为满足企业内部沟通和协作需求而设计的重要工具。在信创企业中,采用私有化安全沟通解决方案…

乐乐音乐Kotlin版

简介 乐乐音乐Kotlin版,主要是基于ExoPlayer框架开发的Android音乐播放器,它支持lrc歌词和动感歌词(ksc歌词、krc歌词、trc歌词、zrce歌词和hrc歌词等)、多种格式歌词转换器及制作动感歌词、翻译歌词和音译歌词。 编译环境 Android Studio Jellyfish | …

计算机毕业设计Python+Tensorflow股票推荐系统 股票预测系统 股票可视化 股票数据分析 量化交易系统 股票爬虫 股票K线图 大数据毕业设计 AI

1、用pycharm打开项目,一定要打开包含manage.py文件所在文件夹 2、配置解释器:建议使用Anaconda(Python 3.8(base)),低于3.8版本的,页面会不兼容 3、安装依赖库:打开pycharm的终端,输入: pip in…

第TR3周:Pytorch复现Transformer

本文为365天深度学习训练营 中的学习记录博客 原作者:K同学啊 任务详情: ●1. 从整体上把握Transformer模型,明白它是个什么东西,可以干嘛 ●2. 读懂Transformer的复现代码(暂时不要过于纠结于某一个点,后面…

重生之我们在ES顶端相遇第9 章- 搜索框最常用的功能 - 搜索建议

文章目录 1 前言2 Term Suggester2.1 基本介绍2.2 使用 demo2.3 常用参数2.3.1 suggest_mode2.3.2 max_edits2.3.3 prefix_length2.3.4 min_word_length 3 Completion Suggester3.1 基本描述3.2 基本使用3.3 查询参数3.3.1 size3.3.2 skip_duplicates3.3.3 fuzzy queries(模糊查…

【WPF开发】安装环境、新建工程

一、安装环境 在安装VS时候,勾选安装开发环境 如果已安装VS,可以到工具中查看是否有相应环境 二、新建工程 点击“创建新项目” 通过顶部过滤,C#,选择“WPF应用(NET.framework)”,并点击“下一…

通过 ACM 论文模版学习 LaTeX 语法 【三、格式】

文章目录 一、LaTeX 简介二、ACM 论文模版三、格式3.1 文章格式3.1.1 注释3.1.2 空格3.1.3 换行 3.2 字体3.2.1 字体样式3.2.2 字体大小2.2.3 字体颜色 一、LaTeX 简介 通过 ACM 论文模版学习 LaTeX 语法 【一、LaTeX简介和安装】 二、ACM 论文模版 通过 ACM 论文模版学习 L…

一款免费开源绿色免安装的透明锁屏工具

一款免费开源绿色免安装的透明锁屏工具 这个工具的特点就是电脑锁屏的时候,仍然显示原桌面,但是无法操作,需要输入密码才可以解锁。输入密码界面也是隐藏的需要按键才能显示输入密码框。 电脑★★★★★透明锁屏工具:https://pa…

canvas-视频绘制

通过Canvas元素来实时绘制一个视频帧,并在视频帧上叠加一个图片的功能可以当作水印。 获取Canvas元素: let canvas document.getElementById(canvas) 通过getElementById函数获取页面中ID为canvas的Canvas元素,并将其存储在变量canvas中。 …

快速将网站从HTTP升级为HTTPS

在当今数字化的世界中,网络安全变的越来越重要,HTTPS(超文本传输安全协议)不仅能够提供加密的数据传输,还能增强用户信任度,提升搜索引擎排名,为网站带来多重益处。所以将网站从HTTP升级到HTTPS…

达利欧对话施一公:如何应对快速变化的世界?

本篇是对达利欧对话施一公:如何应对快速变化的世界?|凤凰《封面》这一视频的翻译与整理, 过程中为符合中文惯用表达有适当删改, 版权归原作者所有. 达利欧:我很兴奋,施教授和我有很多共同点,即使我们来自不…

DynamicDataSource多数据源的管理,动态新增切换数据源

文章目录 多数据源管理单数据源项目父工程版本与依赖yml配置文件实体类新增与修改时间MapperServiceController主启动类测试类 多数据源初始版yml配置文件配置类创建一个AbstractRoutingDataSourceController层测试 DynamicDataSource版本引入依赖yml配置文件Controller层Servi…