java单元测试( Hamcrest 断言)
java单元测试( Hamcrest 断言)
单元测试特征:
1 范围狭窄
2 限于单一类或方法
3 体积小
为什么要编写单元测试?
为了防止错误(很明显!)
而且还可以提高开发人员的生产力,因为单元测试:
(1) 帮助实施——在编码的同时编写测试可以快速反馈正在编写的代码。
(2) 失败时应该易于理解——每个测试在概念上都应该简单,并专注于系统的特定部分。
(3) 作为工程师如何使用被测系统部分的文档和示例(因为书面文档很快就会无可救药地过时)。
在谷歌,80% 的测试都是单元测试。 编写测试的简便性和运行它们的速度意味着工程师每天要运行数千个单元测试。
可维护性的重要性
这个场景有两个关键问题:
(1) 单元测试很脆弱。 它们因无害且无关的更改而中断,该更改没有引入真正的错误。
(2) 单元测试不明确。 很难理解如何修复测试,因为一开始就不清楚测试在做什么。
当代码及其测试有多个贡献者时,这种情况很容易发生(现实生活中的软件项目往往会有很多人同时参与其中)。
争取不变的考验
防止脆弱测试的关键策略是努力编写不需要更改的测试,除非项目的
需求变更:
• 内部重构不应改变测试。
• 新功能应不影响现有功能。
• 错误修复不应要求更新测试。
• 行为改变:这些可能需要改变测试。
Testing Implementation:
Verifies implementation using package-private method
Testing Behaviour:
This test is using the public API, to the extent of almost
playing a game of Connect4.
The resulting behaviour (a change to the board) is checked using a public method
防止脆性测试
1 仅通过调用公共方法(public methods )进行测试。
2 核实结果是什么,而不是如何实现的。
通过以下方式争取不变的测试:
如果您专注于测试实现而不是行为,您将得到脆弱的测试。
所以总是喜欢针对行为进行测试。
编写清晰的单元测试:
Hamcrest 是一个用于在 Java 中编写富有表现力和可读性的断言的库。 它提供了一组匹配器对象,可以与 JUnit 或 TestNG 等测试框架一起使用,以创建更具描述性和灵活性的断言。
Hamcrest assertions 通过允许您以更流畅和自然的方式构建断言来增强测试的可读性。 您可以使用 Hamcrest 匹配器创建自定义断言,以清晰简洁的方式表达预期行为,而不是仅仅依赖测试框架提供的默认断言方法。
以下是 Hamcrest 断言的一些主要特性和优势:
-
流畅易读的语法: Hamcrest 断言使用流畅易读的语法,这使您可以编写非常类似于普通英语语句的断言。 这使得更容易理解断言的意图。
-
可扩展和可定制: Hamcrest 提供了一组丰富的内置匹配器,涵盖常见断言,如相等性、可空性、数字比较、集合内容等。 此外,它还允许您创建自定义匹配器来处理内置匹配器未涵盖的特定断言。
-
可组合性: Hamcrest 匹配器可以使用“and”、“or”和“not”等逻辑运算符进行组合和组合,使您能够从更简单的断言创建复杂的断言。 这允许更灵活和细粒度的断言。
-
诊断消息: Hamcrest 在断言失败时提供详细的诊断消息。 这些消息提供有关预期值和实际值的信息,有助于快速识别断言失败的原因。
下面是将 Hamcrest 断言与 JUnit 结合使用的示例:
导入 org.junit.jupiter.api.Test;
导入静态 org.hamcrest.MatcherAssert.assertThat;
导入静态 org.hamcrest.Matchers.*;公开课 MyTest {@测试public void testStringLength() {String text = "你好,世界!";assertThat(文本,是(notNullValue()));assertThat(text, containsString("你好"));assertThat(文本,hasLength(13));assertThat(文本, anyOf(startsWith("H"), endsWith("!")));}
}
在此示例中,Hamcrest 匹配器用于对字符串执行各种断言。 assertThat
方法用于将匹配器应用于被测试的实际值(text
)。 与默认的 JUnit 断言相比,匹配器(is
、containsString
、hasLength
、anyOf
)提供了更具表现力和描述性的断言。
通过使用 Hamcrest 断言,您可以编写更具可读性和表达力的测试,从而更容易理解预期行为并提高测试代码的整体质量。
另一个示例:
实际结果和预期结果之间的关系由匹配器指定,在本例中为 equalTo。
Hamcrest 匹配器
Hamcrest 有很多“匹配器”,比如 equalTo。
他们可以帮助编写涉及多种类型的断言,包括:
• 字符串——例如,可以检查字符串是否包含子字符串、忽略大小写等。
• 集合——元素是否在集合中; 集合包含什么,忽略顺序等。
如果没有合适的匹配器,很容易编写自己的匹配器。
请参阅 https://www.baeldung.com/java-junit-hamcrest-guide
使您的测试完整而简洁
确保测试包含读者了解它如何得出结果所需的所有信息。
确保它不包含其他不相关和分散注意力的信息。
当测试用例的主体包含读者理解它如何得出结果所需的所有信息时,测试用例就完成了。
当这两个测试用例的主体包含读者需要了解其如何得出结果的所有信息时,这两个测试用例就完成了。
枚举所有的动作使得方法更长并且防止将移动序列重新用作辅助方法,但更清楚发生了什么。 棋盘上增加了两列垂直棋子,红色在第 0 列获胜
不要DRY测试
DRY——不要重复自己:工程师需要更新一段代码而不是跟踪所有实例。
缺点:可以使代码不那么清晰,需要遵循引用链。
为了使代码更易于使用,这可能是一个很小的代价……但是成本/收益分析在测试中的表现不同:
• 我们希望测试在软件更改时中断
• 生产代码具有测试套件的优势,可确保在事情变得复杂时它仍能正常工作。 测试应该独立存在!(当测试需要测试时出了问题)
湿而不干(DAMP not DRY)
DAMP:描述性的和有意义的短语
DAMP 不能替代 DRY——它是补充。
“助手”方法可以通过使测试更简洁来帮助使测试更清晰——分解出重复的步骤,这些步骤的细节与被测试的行为无关。
但是重构应该着眼于使测试更具可读性和描述性,而不仅仅是为了减少重复。
不要包括清晰和简洁。
当测试用例不包含其他分散注意力或不相关的信息时,它就是简洁的。
我们的测试现在包括很多不需要的动作在测试场景并使电路板更难可视化以及测试结果应该是什么。
不要测试方法——测试行为
但是一个方法可能有不止一种行为和/或一些需要更多测试的棘手的极端情况。
例如,makeMove 可以有多种行为,具体取决于棋盘的状态。
对该方法的一次测试没有任何意义,并且可能不是很清楚也不简洁。
更好的方法:为每个行为编写测试。
测试行为
行为是系统在特定状态下如何响应一系列输入的保证。
行为可以表示为“给定 X,当 Y,然后 Z”
例如:
给定一个 Connect4 棋盘,RED 首先开始,当 RED 下了一个棋子后,接下来就轮到 YELLOW 了。
编写行为驱动的测试
行为驱动的测试更倾向于阅读自然语言,因此相应地构建它们
在被测试的行为之后命名测试.
一个好的名称描述了正在测试的动作(“何时”)和预期结果(“然后”),有时还描述了状态(“给定”)。
一个好的技巧是以“应该”开头的名称,例如
shouldInitializeCorrectly
shouldChangePieceAfterTurn
shouldEndGameWithWinnerWhenFourInARowHorizontally etc.
不要把逻辑放在测试中
不要在测试或逻辑操作中放置条件或循环。
测试应该读作简单的事实陈述,而不是同样需要测试的代码块!
最好只初始化一个较小的 2x2 板并明确检查每个位置
Making Your Unit Tests Clear
1 Make your tests concise and complete (DAMP and not too DRY!)
2 Don’t structure tests around methods – instead structure around behaviours
3 Use the Given-When-Then pattern for testing behaviour
4 Name Tests after the Behaviour Being Tested
5 Don’t put logic in tests
相关文章:

java单元测试( Hamcrest 断言)
java单元测试( Hamcrest 断言) 单元测试特征: 1 范围狭窄 2 限于单一类或方法 3 体积小 为什么要编写单元测试? 为了防止错误(很明显!) 而且还可以提高开发人员的生产力,因为单元测试: (1) 帮助实施——在…...

讨论和总结 树模型 的三种序列化 方式的区别(模型存储大小、序列化所用内存、序列化速度)...
一、前言 本文总结常用树模型: rf,xgboost,catboost和lightgbm等模型的保存和加载(序列化和反序列化)的多种方式,并对多种方式从运行内存的使用和存储大小做对比 二、模型 2.1 安装环境 pip install xgboos…...

Halcon中的一些3D算子
一、记录一些Halcon里的关于3D的算子 1.read_object_model_3d 从文件读取一个3d模型 如下图,读的一个ply文件出来是个3d点云模型 2.visualize_object_model_3d 交互式展示3d模型 即上个算子读出来后,通过这个算子可以把3d模型显示出来旋转、平移&am…...

Android:Selector + Layer-lists 实现 AppCompatCheckBox
最近做项目涉及到一些UI相关的东东,虽然比较简单,但是也很有趣,写两篇简短的博客记录一下。 一."Selector 两张图片"实现 AppCompatCheckBox AppCompatCheckBox 是 androidx的一个widget:androidx.appcompat.widget.…...
TreeMap类型添加数据
package com.test.Test11;import java.util.*;public class Test02 {public static void main(String[] args) {/** 增加:put(K key,V value)* 删除:clear() remove(Object key)* 修改:* 查看:entrySet() get(Object key) keySet(…...

iOS 16 UI 设计系统免费在线使用方法
1、iOS 16 UI 设计系统中有什么? iOS 16 UI 设计系统通常包含以下组件和元素: 1. 按钮:包括操作按钮、图标按钮、导航按钮、滚动按钮、切换按钮、单选按钮、复选框按钮、呼叫按钮等各种类型的按钮。 2. 窗口和 UI 控件:包括标签…...

【接口测试】JMeter接口关联测试
1 前言 我们来学习接口管理测试,这就要使用到JMeter提供的JSON提取器和正则表达式提取器了,下面我们来看看是如何使用的吧。 2 JSON提取器 1、添加JSON提取器 在线程组右键 > 添加 > 后置处理器 > JSON提取器 2、JSON提取器参数说明 N…...

腾讯云服务器ping不通解决方法(公网IP/安全组/系统多维度)
腾讯云服务器ping不通什么原因?ping不通公网IP地址还是域名?新手站长从云服务器公网IP、安全组、Linux系统和Windows操作系统多方面来详细说明腾讯云服务器ping不通的解决方法: 目录 腾讯云服务器ping不通原因分析及解决方法 安全组ICMP协…...
【C++/嵌入式笔试面试八股】一、32.封装
封装 08.C++中struct和class的区别🍊 相同点 两者都拥有成员函数、公有和私有部分任何可以使用class完成的工作,同样可以使用struct完成不同点 两者中如果不对成员不指定公私有,struct默认是公有的,class则默认是私有的class默认是private继承, 而struct默认是public继…...
【算法】Transform to Chessboard 变为棋盘
文章目录 Transform to Chessboard 变为棋盘问题描述:分析代码 Transform to Chessboard 变为棋盘 问题描述: 一个 n x n 的二维网络 board 仅由 0 和 1 组成 。每次移动,你能任意交换两列或是两行的位置。 返回 将这个矩阵变为 棋盘 所需…...
vue通过封装$on定义全局事件
我们先在vue项目的src跟目录下创建一个文件夹 叫 utils 下面创建一个js文件夹 叫 bus.js 参考代码如下 import Vue from "vue"; export default new Vue();然后 我们就可以来用了 在需要定义事件的组件中编写 <template><div><h1>Hello world!&…...
资产管理规范
生产系统资产管理规范 1. 引言 生产系统的资产管理是确保生产系统正常运行和提高生产效率的关键因素之一。本文档旨在制定一套规范,以确保生产系统中的资产,包括服务器和软件等,得到有效管理和保护。 2. 资产分类 生产系统资产可根据其性质…...

已解决:如何从别人的仓库那里克隆到自己的仓库,并修改代码并提交。
一、场景 拉取项目代码后,如果要共同开发一个项目的自动化代码,此时需要把自己写的代码部分提交到代码仓库。 可以用pycharm把修改的代码push到代码仓库 二、操作方法 1.从别人的仓库那里点击fork,将仓库克隆到自己的仓库。 2.在pychar…...

剑指 Offer 18. 删除链表的节点
🚀 作者简介:一名在后端领域学习,并渴望能够学有所成的追梦人。 🚁 个人主页:不 良 🔥 系列专栏:🛸剑指 Offer 📕 学习格言:博观而约取,厚积而薄…...

WiFi 6 vs WiFi 5
在现代无线通信领域,WiFi已经成为人们日常生活中不可或缺的一部分。随着技术的不断发展,WiFi标准也在不断更新和演进。WiFi 6(802.11ax)和WiFi 5(802.11ac)是当前两个主要的WiFi标准。 本文将详细介绍WiFi …...
PHP语言基础
一.标记风格 标记风格分为四类(推荐XML) 1.XML风格 <?php echo这是xml风格‘; ?> 注意:结束标识符必须单独另起一行,并且不能有空格。在标识符前后有其他符号或者字符也会发生错误。 2.脚本风格 <script languagephp> …...

怎么用Excel VBA写一个excel批量合并的程序?
您可以按照以下VBA代码来实现把同一路径上的所有工作簿合并到同一个工作簿中: VBA Option Explicit Sub MergeWorkbooks() Dim path As String, fileName As String, sheet As Worksheet Dim targetWorkbook As Workbook, sourceWorkbook As Workbook Dim workshe…...
WuThreat身份安全云-TVD每日漏洞情报-2023-05-22
漏洞名称:Apple WebKit 任意代码执行漏洞 漏洞级别:中危 漏洞编号:CVE-2023-32373 相关涉及:Apple iOS和iPadOS 16.4.1 漏洞状态:在野 参考链接:https://tvd.wuthreat.com/#/listDetail?TVD_IDTVD-2023-12579 漏洞名称:海康威视部分iVMS系统存在文件上传漏洞 漏洞级别:未定义…...

Eclipse教程 Ⅵ
今天分享Eclipse Java 构建路径、Eclipse 运行配置(Run Configuration)和Eclipse 运行程序 Eclipse Java 构建路径 设置 Java 构建路径 Java构建路径用于在编译Java项目时找到依赖的类,包括以下几项: 源码包项目相关的 jar 包及类文件项目引用的的类…...

Seaborn.load_dataset()加载数据集失败最佳解决方法
load_dataset() 是 Seaborn 库中提供的一个函数,用于加载一些原始数据集。这些数据集包含了许多经典的数据集,比如鸢尾花数据集、小费数据集等,这些数据集在数据可视化和机器学习中非常常见。 使用 load_dataset() 函数可以方便地获取这些数…...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)
前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 …...