Java IDEA JUnit 单元测试
JUnit是一个开源的 Java 单元测试框架,它使得组织和运行测试代码变得非常简单,利用JUnit可以轻松地编写和执行单元测试,并且可以清楚地看到哪些测试成功,哪些失败
JUnit 还提供了生成测试报告的功能,报告不仅包含测试的成功率,还能统计被测试代码的覆盖率。通过进行单元测试,我们可以确保每个方法按照预期正确运行。
如果我们修改了某个方法的代码,只需要确保相应的单元测试通过,就可以认为修改是正确的。此外,测试代码本身也可以作为示例代码,用于演示如何调用该方法。
几乎所有的IDE工具都集成了JUnit,我们这里使用IDEA
参考 编写JUnit测试 - 廖雪峰的官方网站 (liaoxuefeng.com)
目录
编写JUnit单元测试
使用Fixture自动执行代码
异常测试
条件测试
参数化测试
编写JUnit单元测试
用递推的方法写一个计算n的阶乘的Java方法。
我们可以针对刚刚写的Java编写一个对应的测试代码对其进行测试,在IDEA中可以直接右击点击生成Junit测试。
点击确定生成一个FactorialTest.java文件。
这是JUnit会把带有@Test的方法识别为测试方法,因此需要给测试方法加上@Test注解,测试方法内部用assertEquals(1, Factorial.fact(1))表示期望Factorial.fact(1)返回1。
运行这个测试程序,JUnit就会给出成功的测试和失败的测试,还可以生成测试报告,不仅包含测试的成功率,还可以统计测试的代码覆盖率,即被测试的代码本身有多少经过了测试。
Factorial.java
public class Factorial {public static long fact(long n) {long r = 1;for (long i = 1; i <= n; i++) {r = r * i;}return r;}
}
FactorialTest.java
import static org.junit.jupiter.api.Assertions.*;import org.junit.jupiter.api.Test;public class FactorialTest {@Testvoid testFact() {assertEquals(1, Factorial.fact(1));assertEquals(2, Factorial.fact(2));assertEquals(6, Factorial.fact(3));assertEquals(3628800, Factorial.fact(10));assertEquals(2432902008176640000L, Factorial.fact(20));}}
使用Fixture自动执行代码
Fixture是JUnit提供的编写测试前准备、测试后清理的固定代码,可以用于测试前和测试后自动执行代码。
先编写一个简单的实现加减法功能的Calculator代码。
但是测试的时候,需要先初始化对象,可以使用@BeforeEach和@AfterEach标记的方法,@BeforeEach标记的方法会在执行每个@Test的方法之前调用,而@AfterEach标记的方法会在执行每个@Test的方法之后调用,这样就可以通过@BeforeEach和@AfterEach标记来自动实现对象的生成和销毁。
然后再编写我们的测试代码。
运行测试代码,可以看到测试结果。
如果需要在所有@Test方法运行前后仅运行一次,那么可以使用@BeforeAll和@AfterAll对方法进行标记。
Calculator.java
public class Calculator {private long n = 0;public long add(long x) {n = n + x;return n;}public long sub(long x) {n = n - x;return n;}
}
CalculatorTest.java
import static org.junit.jupiter.api.Assertions.*;import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;public class CalculatorTest {Calculator calculator;@BeforeEachpublic void setUp() {this.calculator = new Calculator();}@AfterEachpublic void tearDown() {this.calculator = null;}@Testvoid testAdd() {assertEquals(100, this.calculator.add(100));assertEquals(150, this.calculator.add(50));assertEquals(130, this.calculator.add(-20));}@Testvoid testSub() {assertEquals(-100, this.calculator.sub(100));assertEquals(-150, this.calculator.sub(50));assertEquals(-130, this.calculator.sub(-20));}
}
异常测试
对于可能抛出的异常进行测试是测试的重要环节,因此在编写JUnit测试的时候,除了正常的输入输出,还要特别针对可能导致异常的情况进行测试。
在计算阶乘的方法中增加对参数n的检查,如果n为负数,则直接抛出异常IllegalArgumentException。
在测试代码中,我们可以编写一个@Test方法专门测试异常,JUnit提供assertThrows函数来期望捕获一个指定的异常。
运行测试代码,可以看到测试结果。
Factorial.java
public class Factorial {public static long fact(long n) {if (n < 0) {throw new IllegalArgumentException();}long r = 1;for (long i = 1; i <= n; i++) {r = r * i;}return r;}
}
FactorialTest.java
import static org.junit.jupiter.api.Assertions.*;import org.junit.jupiter.api.Test;public class FactorialTest {@Testvoid testFact() {assertEquals(1, Factorial.fact(1));assertEquals(2, Factorial.fact(2));assertEquals(6, Factorial.fact(3));assertEquals(3628800, Factorial.fact(10));assertEquals(2432902008176640000L, Factorial.fact(20));}@Testvoid testNegative() {assertThrows(IllegalArgumentException.class, () -> {Factorial.fact(-1);});}
}
条件测试
条件测试可以在满足某种条件下执行某些测试方法,不执行某些测试方法。
编写一个程序,该程序中的方法在Windows上跑和在Linux上跑的代码路径不同。
编写测试代码的时候,用@EnableOnOs标记方法,指定只有在特定系统下才执行该测试方法。
用@DisabledOnOs标记方法表示不在某个系统上执行该方法。
用@DisabledOnJre标记方法表示只能在高于特定Java版本的测试。
用@EnabledIfSystemProperty(named = "os.arch", matches = ".*64.*")标记,表示只能在64位操作系统上执行的测试。
用@EnabledIfEnvironmentVariable标记方法表示需要传入环境变量DEBUG=true才能执行的测试。
运行测试代码,可以看到测试结果。
Config.java
public class Config {public String getConfigFile(String filename) {String os = System.getProperty("os.name").toLowerCase();if (os.contains("win")) {return "C:\\" + filename;}if (os.contains("mac") || os.contains("linux") || os.contains("unix")) {return "/usr/local/" + filename;}throw new UnsupportedOperationException();}
}
ConfigTest.java
import static org.junit.jupiter.api.Assertions.*;import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.*;public class ConfigTest {Config config;@BeforeEachpublic void setUp() {this.config = new Config();}@AfterEachpublic void tearDown() {this.config = null;}@Test@EnabledOnOs(OS.WINDOWS)void testWindows() {assertEquals("C:\\test.ini", config.getConfigFile("test.ini"));}@Test@EnabledOnOs({OS.LINUX, OS.MAC})void testLinuxAndMac() {assertEquals("/usr/local/test.cfg", config.getConfigFile("test.cfg"));}@Test@DisabledOnOs(OS.WINDOWS)void testOnNonWindowsOs() {// TODO: this test is disabled on windows}@Test@DisabledOnJre(JRE.JAVA_8)void testOnJava9OrAbove() {// TODO: this test is disabled on java 8}@Test@EnabledIfSystemProperty(named = "os.arch", matches = ".*64.*")void testOnlyOn64bitSystem() {// TODO: this test is only run on 64 bit system}@Test@EnabledIfEnvironmentVariable(named = "DEBUG", matches = "true")void testOnlyOnDebugMode() {// TODO: this test is only run on DEBUG=true}
}
参数化测试
JUnit提供了一个@ParameterizedTest注解,用来进行参数化测试。参数化测试和普通测试稍微不同的地方在于,一个测试方法需要接收至少一个参数,然后,传入一组参数反复运行。
编写一个方法,该方法把字符串的第一个字母变为大写,后续字母变为小写。
在编写测试代码的时候,需要给出输入和预期输出,可以通过@MethodSource注解,它允许我们编写一个同名的静态方法来提供测试参数,编写一个静态方法testCapitalize返回了一组测试参数,每个参数都包含两个String,作为测试方法的两个参数传入。
还可以使用@CsvSource标记传入测试参数的方法,它的每一个字符串表示一行,一行包含的若干参数用 , 分隔。
如果测试数据很多,可以把测试数据提到一个独立的CSV文件中,标注上@CsvFileSource表示从CSV文件中读取数据。
由于JUnit只在classpath中查找指定的CSV文件,因此,test-capitalize.csv这个文件要放到src/main/resources目录下,内容格式如下图所示。
运行测试程序,测试结果如下图所示。
StringUtils.java
public class StringUtils {public static String capitalize(String s) {if (s.length() == 0) {return s;}return Character.toUpperCase(s.charAt(0)) + s.substring(1).toLowerCase();}
}
StringUtilsTest.java
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;import static org.junit.jupiter.api.Assertions.*;public class StringUtilsTest {
// @ParameterizedTest
// @MethodSource
// void testCapitalize(String input, String result) {
// assertEquals(result, StringUtils.capitalize(input));
// }
//
// static List<Arguments> testCapitalize() {
// return List.of( // arguments:
// Arguments.of("abc", "Abc"), //
// Arguments.of("APPLE", "Apple"), //
// Arguments.of("gooD", "Good"));
// }// @ParameterizedTest
// @CsvSource({"abc, Abc", "APPLE, Apple", "gooD, Good"})
// void testCapitalize(String input, String result) {
// assertEquals(result, StringUtils.capitalize(input));
// }@ParameterizedTest@CsvFileSource(resources = {"test_capitalize.csv"})void testCapitalizeUsingCsvFile(String input, String result) {assertEquals(result, StringUtils.capitalize(input));}
}
相关文章:

Java IDEA JUnit 单元测试
JUnit是一个开源的 Java 单元测试框架,它使得组织和运行测试代码变得非常简单,利用JUnit可以轻松地编写和执行单元测试,并且可以清楚地看到哪些测试成功,哪些失败 JUnit 还提供了生成测试报告的功能,报告不仅包含测试…...
深入理解 c++ 函数模板
函数模板是C中的一种强大特性,它允许程序员编写一个可以处理多种数据类型的函数。通过使用模板,我们可以编写一次函数,然后在多种数据类型上使用它,这大大提高了代码的复用性。 1. 基本概念 函数模板是一种参数化类型的工具&…...

系列十二、Linux中安装Zookeeper
一、Linux中安装Zookeeper 1.1、下载安装包 官网:Index of /dist/zookeeper/zookeeper-3.4.11 我分享的链接: 链接:https://pan.baidu.com/s/14Hugqxcgp89f2hqGWDwoBw?pwdyyds 提取码:yyds 1.2、上传至/opt目录 1.3、解…...

k8s之陈述式资源管理
1.kubectl命令 kubectl version 查看k8s的版本 kubectl api-resources 查看所有api的资源对象的名称 kubectl cluster-info 查看k8s的集群信息 kubectl get cs 查看master节点的状态 kubectl get pod 查看默认命名空间内的pod的信息 kubectl get ns 查看当前集群所有的命…...
7天玩转 Golang 标准库之 http/net
在构建web应用时,我们经常需要处理HTTP请求、做网页抓取或者搭建web服务器等任务,而Go语言在这方面为我们提供了强大的内置工具:net/http标准库,它为我们操作和处理HTTP协议提供了便利。 基础用法 一:处理HTTP请求 首…...

钡铼技术集IO数据采集可编程逻辑控制PLC无线4G环保物联网关
背景 数据采集传输对于环保企业进行分析和决策是十分重要的,而实时数据采集更能提升环保生产的执行力度,从而采取到更加及时高效的措施。因此实时数据采集RTU成为环保企业的必备产品之一。 产品介绍 在推进环保行业物联网升级过程中,环保RTU在…...

STM32CubeMX教程10 RTC 实时时钟 - 周期唤醒、闹钟A/B事件和备份寄存器
目录 1、准备材料 2、实验目标 3、实验流程 3.0、前提知识 3.1、CubeMX相关配置 3.1.1 、时钟树配置 3.1.2、外设参数配置 3.1.3 、外设中断配置 3.2、生成代码 3.2.1、外设初始化函数调用流程 3.2.2、外设中断函数调用流程 3.2.3、添加其他必要代码 4、常用函数 …...

HarmonyOS4.0系统性深入开发08服务卡片架构
服务卡片概述 服务卡片(以下简称“卡片”)是一种界面展示形式,可以将应用的重要信息或操作前置到卡片,以达到服务直达、减少体验层级的目的。卡片常用于嵌入到其他应用(当前卡片使用方只支持系统应用,如桌…...

002文章解读与程序——中国电机工程学报EI\CSCD\北大核心《计及源荷不确定性的综合能源生产单元运行调度与容量配置两阶段随机优化》已提供下载资源
👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆👆下载资源链接Ǵ…...

Typora快捷键设置详细教程
文章目录 一、快捷键设置步骤二、设置快捷键简单案例参考资料 一、快捷键设置步骤 在typora软件中,快捷键的设置步骤主要为: 打开【文件】–>【偏好设置】,找到【通用】–>【打开高级设置】,找到 conf.user.json 文件。 然…...

《异常检测——从经典算法到深度学习》25 基于深度隔离林的异常检测算法
《异常检测——从经典算法到深度学习》 0 概论1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法3 基于One-Class SVM的异常检测算法4 基于高斯概率密度异常检测算法5 Opprentice——异常检测经典算法最终篇6 基于重构概率的 VAE 异常检测7 基于条件VAE异常检测8 Donut: …...
第7章 1 异常处理
bug的由来及分类 p81 字符串形式表示的数字之间也可以比较大小 import re ageinput(年龄:) if age>18:print(age)列表的append操作每次只能添加一个元素: lst[] lst.append(A) lst.append(B) # lst.append(A,B) 错误python中的异常处理机制 p82 t…...

昇腾910平台安装驱动、固件、CANN toolkit、pytorch
本文使用的昇腾910平台操作系统是openEuler,之前没了解过,不过暂时感觉用起来和centOS差不多。系统架构是ARM,安装包基本都是带aarch64字样,注意和x86_64区别开,别下错了。 安装依赖 cmake 通过yum安装的cmake版本较…...
【数据挖掘】模型融合
模型融合是指将多个不同的机器学习模型组合起来,通过综合多个模型的预测结果来得到更准确的预测结果。模型融合可以提高模型的鲁棒性,减小模型的方差,提高模型的泛化能力。 常见的模型融合方法包括平均法、投票法和堆叠法。 平均法(Averagin…...

DM、Oracle、GaussDB、Kingbase8(人大金仓数据库)和HIVE给列增加注释
DM数据库给列增加注释 1、创建表 CREATE TABLE test222 ( id int NOT NULL PRIMARY KEY, name varchar(1000) DEFAULT NULL, email varchar(1000) DEFAULT NULL, phone varchar(1000) DEFAULT NULL ) 2、给列添加注释 comment on column TEST222.NAME is 这是一个列注释; 例如…...

C语言实例_stdlib.h库函数功能及其用法详解
一、前言 C语言作为一种高效、灵活的编程语言,标准库的使用对于开发人员来说是不可或缺的。其中,stdlib.h是C语言中一个重要的标准库头文件,提供了许多常用的函数和工具,以便开发人员能够更加便捷地进行内存管理、字符串处理、随…...
Error in onLoad hook: “URIError: URI malformed“ found in…报错处理以及完善uniapp针对对象传参
使用uniapp传参的过程中遇到这么一个问题,当我们需要传整个对象作为参数时,我会先将这个对象先编码,然后再解码,从而获取到怎么参数,平常实操的时候也没有遇到过问题,但是今天测试的时候,刚好一…...

c语言-位操作符练习题
文章目录 前言一、n&(n-1)的运用场景(n为整数)二、&1 和 >>的应用场景总结 前言 本篇文章介绍利用c语言的位操作符解决一些练习题,目的是掌握各个位操作符的使用和应用场景。 表1.1为c语言中的位操作符 操作符含义&按位与|按位或^按位异或~按位…...

园林机械部件自动化三维测量检测形位公差-CASAIM自动化三维检测工作站
随着园林机械的广泛应用,对其机械部件的精确测量需求也日益增加。传统的测量方法不仅效率低下,而且精度难以保证,因此,自动化三维测量技术成为了解决这一问题的有效途径。本文将重点介绍CASAIM自动化三维检测工作站在园林机械部件…...

o2o生活通全开源尊享版+多城市切换+企业付款+交友IM+平台快报
搭建教程 1.把 pigo2ov282.sql 文件里面的网址 test.souho.net 全部批量替换为你的自己的 2.使用 phpmyadmin 导入 pigo2ov282.sql 到你的数据库(直接访问/phpmyadmin 即可) 3.修改数据库文件/conf/db.php 里的数据库连接信息(请勿使用记事本…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...

算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...
【Elasticsearch】Elasticsearch 在大数据生态圈的地位 实践经验
Elasticsearch 在大数据生态圈的地位 & 实践经验 1.Elasticsearch 的优势1.1 Elasticsearch 解决的核心问题1.1.1 传统方案的短板1.1.2 Elasticsearch 的解决方案 1.2 与大数据组件的对比优势1.3 关键优势技术支撑1.4 Elasticsearch 的竞品1.4.1 全文搜索领域1.4.2 日志分析…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!
目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

spring Security对RBAC及其ABAC的支持使用
RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型,它将权限分配给角色,再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...