单元测试工具-Junit

news2024/12/24 8:56:36

文章目录

  • 一. 认识Junit
  • 二. Junit中常用的注解
    • 1. @Test
    • 2. @Disabled
    • 3. @BeforeAll & @AfterAll
    • 4. @BeforeEach & @AfterEach
  • 三. @ParameterizedTest参数化
    • 1. 单参数
    • 2. 多参数
      • 2.1. CSV 获取参数
      • 2.2. 方法获取参数
  • 四. @Order控制测试用例的执行顺序
  • 五. 断言
  • 六. 测试套件
    • 1. 通过Class运行测试用例
    • 2. 通过包运行测试用例

一. 认识Junit

JUnit 是一个用于编写和运行 Java 程序的开源框架,它支持自动化单元测试,可以帮助开发人员测试代码的正确性和健壮性。

JUnit 提供了一组注解、断言和测试运行器,可以方便地编写和运行单元测试。

在进行自动化测试时,比如使用 Selenium 自动化测试框架编写一些测试用例脚本,那么可能就需要执行很多测试用例的,此时我们就需要一个工具来管理这些测试用例,而 Junit 就是一个很好的管理工具。

二. Junit中常用的注解

比较常用的是 JUnit5 版本,要使用需要引入以下依赖:

<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-api</artifactId>
    <version>5.9.2</version>
    <scope>test</scope>
</dependency>

其中的常用的注解有以下几个:

注解说明
@Test标识单元测试方法。
@BeforeEach在每个测试方法之前执行。
@AfterEach在每个测试方法之后执行。
@BeforeAll在所有测试方法之前执行,只会执行一次。
@AfterAll在所有测试方法之后执行,只会执行一次。
@Disabled标识禁用的测试类或测试方法。

1. @Test

@Test注解标识在方法上面,表示当前的方法是一个单元测试方法,通过 @Test 标识的单元测试方法,不需要在main中,也可以直接执行。

演示代码:

import org.junit.jupiter.api.Test;

public class JunitTest {
    @Test
    void Test01() {
        System.out.println("这是JunitTest里面的Test01");
    }

    @Test
    void Test02() {
        System.out.println("这是JunitTest里面的Test02");
    }
}

需要注意的是此时编译器中的几个运行按钮:

img

执行类中全部单元测试方法结果:

img

其中“ √ ”表示测试通过,如果是出现“ ! / X ”就表示测试错误。

2. @Disabled

当使用@Disabled注释时,表示当前的单元测试方法不会被执行(忽略)。

演示代码:

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class JunitTest {
    @Test
    void Test01() {
        System.out.println("这是JunitTest里面的Test01");
    }

    @Test
    void Test02() {
        System.out.println("这是JunitTest里面的Test02");
    }
    @Disabled
    void Test03() {
        WebDriver webDriver = new ChromeDriver();
        webDriver.get("https://www.baidu.com");
        webDriver.findElement(By.cssSelector("#s-top-left > a:nth-child(6)"));
    }
}

执行所有测试用例结果:

Test03未被执行。

img

3. @BeforeAll & @AfterAll

@BeforeAll:当前的方法需要在当前类下所有用例执行之前执行一次(只会执行一次),且被该注解修饰的方法必须为静态方法,通常可以将类似创建驱动,打开网页的操作放在此注解下。

@AfterAll:当前的方法需要在当前类下所有用例执行之后执行一次(只会执行一次),且被该注解修饰的方法必须为静态方法,通常可以将类似关闭浏览器的操作放在此注解下。

演示代码:

@BeforeAll
static void SetUp() {
    System.out.println("这是BeforeAll里面的语句");
}
@AfterAll
static void TearDown() {
    System.out.println("这是AfterAll的语句");
}

执行结果:

img

4. @BeforeEach & @AfterEach

@BeforeEach:当前的方法需要在每个用例执行之前都执行一次。

@AfterEach:当前的方法需要在每个用例执行之后都执行一次。

演示代码:

@BeforeEach
void BeforeEachTest() {
    System.out.println("这是BeforeEach里面的语句");
}
@AfterEach
void AfterEachTest() {
    System.out.println("这是AfterEach里面的语句");
}

执行结果:

img

三. @ParameterizedTest参数化

参数化就是尽可能的通过一个用例,多组参数来模拟用户的行为,在使用参数化注解之前需要先用@parameterizedTest声明该方法为参数化方法,然后再通过注解提供参数的来源,要注意 @ParameterizedTest 和 @Test 不能同时使用。

使用 @parameterizedTest 需要引入以下依赖:

<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-params</artifactId>
    <version>5.9.2</version>
</dependency>

1. 单参数

单参数,指的是传递的参数类型是单种形式的。

主要使用注解@ValueSource(数据类型方法={参数1,参数2…}),数据类型方法就是在类型名称后面加上s

演示代码:

@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void Test04(int num) {
    System.out.println(num);
}

将类中的 Before 和 After 标识的方法先都注释掉,只执行 Test04,方便观察结果。

img

传入 String 类型也是可以的。

@ParameterizedTest
@ValueSource(strings = {"1", "2", "3"})
void Test05(String number) {
    System.out.println(number);
}

执行结果:

img

2. 多参数

多参数,指的是传递的参数可以是多种类型的。

2.1. CSV 获取参数

首先可以使用@CsvSource({“数据组合1”,“数据组合2”…})注解**,**每个双引号是一组参数,可以传入多种类型的参数。

演示代码:

@ParameterizedTest
@CsvSource({"1, 张三", "2, 李四", "3, 王五"})
void Test06(int num, String name) {
    System.out.println("num:" + num + ", name:" + name);
}

执行结果:

img

假设上述参数有很多,在注解处手动编写数据源就有些不方便,我们这时就可以借助第三方.csv文件来读取数据源。

CSV 获取参数使用@CsvFileSource(resources = "____.csv")注解

此时我们可以在resources中创建一个test01.csv文件(.csv 和 参数必须相同),添加如下内容:

1, 张三
2, 李四
3, 王五
4, 赵六

演示代码:

@ParameterizedTest
@CsvFileSource(resources = "test01.csv")
void Test07(int num, String name) {
    System.out.println("num:" + num + ", name:" + name);
}

执行结果:

img

2.2. 方法获取参数

方法获取参数,通过@MethodSource("方法名")注解来实现,需要构造与方法名对应的方法 ,在对应的方法中,返回相应类型的参数。

演示代码:

public static Stream<Arguments> Generator() {
    return Stream.of(Arguments.arguments(1, "张三"),
            Arguments.arguments(2, "李四"),
            Arguments.arguments(3, "王五")
    );
}
@ParameterizedTest
@MethodSource("Generator")
void Test08(int num, String name) {
    System.out.println(num + ":" + name);
}

执行结果:

img

四. @Order控制测试用例的执行顺序

要注意,Junit 每个类中的单元测试的方法的执行顺序并不是从上往下的,它默认的执行顺序是不确定的,是根据 Junit 的运行机制来的,这个就不做介绍了。

如果在实际测试中,我们需要完成连贯的多个步骤的测试,是需要规定测试用例执行的顺序的,就可以通过给测试方法添加@Order注解并指定一个整数值,可以提供一致和可预测的执行顺序。

但使用@Order注解前,需要先使用@TestMethodOrder类注解并设置参数为MethodOrderer.OrderAnnotation.class说明当前类下所有的用例需要按照@Order注解来控制测试方法的执行顺序。

当设置@TestMethodOrder类注解的参数为MethodOrderer.Random.class就恢复默认的执行顺序了,@Order注解就不生效了(跟不写效果一样@TestMethodOrder)。

演示代码:

import org.junit.jupiter.api.*;
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
//@TestMethodOrder(MethodOrderer.Random.class)
public class JunitTest01 {
    @Order(2)
    @Test
    void C() {
        System.out.println("C测试用例");
    }

    @Order(3)
    @Test
    void B() {
        System.out.println("B测试用例");
    }

    @Order(1)
    @Test
    void D() {
        System.out.println("D测试用例");
    }

    @Order(4)
    @Test
    void A() {
        System.out.println("A测试用例");
    }
}

执行结果:

img

五. 断言

JUnit 5 中,断言方法位于 org.junit.jupiter.api.Assertions 类中。

通过Assertions类实现的断言可以在测试中验证预期结果是否与实际结果相符,如果断言失败,则测试将被标记为失败(!,会报错),并提供有关错误的详细信息,这有助于快速定位和修复问题。

断言方法说明
assertEquals(expected, actual)验证两个对象是否相等。可以用于比较基本数据类型、对象和数组。
assertTrue(condition)验证条件是否为真。如果条件为真,则测试通过;否则,测试失败。
assertFalse(condition)验证条件是否为假。如果条件为假,则测试通过;否则,测试失败。
assertNull(actual)验证对象是否为 null。如果对象为 null,则测试通过;否则,测试失败。
assertNotNull(actual)验证对象是否不为 null。如果对象不为 null,则测试通过;否则,测试失败。
assertSame(expected, actual)验证两个对象引用是否相同。即判断两个对象是否指向同一个内存地址。
assertNotSame(unexpected, actual)验证两个对象引用是否不相同。
assertArrayEquals(expectedArray, actualArray)验证两个数组是否相等。用于比较数组的元素是否相等。
assertThrows(expectedType, executable)验证代码块是否抛出了特定类型的异常。
assertTimeout(duration, executable)验证代码块是否在指定的时间内执行完成,超过指定时间则测试失败。

演示代码:

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

public class JunitTest02 {
    @Test
    public void test() {
        String str = "helloworld";
        assertEquals("helloworld", str);
        assertTrue(1 == 1);
        assertFalse(2 < 1);
        assertNotNull(str);
        assertNull(str);
    }
}

执行结果:

报错了,单元测试执行预期结果与实际结果不相符,str并不为null

img

六. 测试套件

当有多个测试类时,挨个去手动运行,会很繁琐耗时,我们可以使用测试套件来指定多个类或者指定多个包来运行类下或者包下的所有测试用例。

要使用测试套件,首先我们需要先创建一个类,通过@Suite注解标识该类为测试套件类。

使用 Suite 需要引入引擎 engine 依赖:

<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter-engine</artifactId>
    <version>5.9.1</version>
</dependency>

使用测试套件,也需要引入依赖项:

<!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite -->
<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-suite</artifactId>
    <version>1.9.1</version>
</dependency>
 

1. 通过Class运行测试用例

使用@SelectClasses({指定类, 指定类, 指定类})类注解,通过参数中指定对应的类,然后对类中的测试用例进行执行,按照从前往后的顺序执行。

演示代码:

import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;

@Suite
@SelectClasses({JunitTest02.class, JunitTest.class, JunitTest01.class})
public class RunSuite {
}

执行结果:

img

2. 通过包运行测试用例

使用@SelectPackages(value = {"包1", "包2","..."})类注解,通过参数中指定对应的包,然后对包中的测试用例进行执行,但是扫描的包不可以和当前的类在同一个包下面。

演示代码:

Test01 包下 test001。

package Test01;

import org.junit.jupiter.api.Test;

public class Test1 {
    @Test
    void test001() {
        System.out.println("Test1 pacage test001");
    }
}

Test02 包下 test002。

package Test02;

import org.junit.jupiter.api.Test;

public class Test2 {
    @Test
    void test002() {
        System.out.println("Test2 pacage test002");
    }
}

RunSuite2。

import org.junit.platform.suite.api.SelectPackages;
import org.junit.platform.suite.api.Suite;

@Suite
@SelectPackages(value = {"Test01", "Test02"})
public class RunSuite2 {
}

执行结果:

img

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

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

相关文章

node插件MongoDB(三)—— 库mongoose 的使用和数据类型(一)

前言 提示&#xff1a;使用mongoose 的前提是你安装了node和 MongoDB。 mongoose 官网文档&#xff1a;http://mongoosejs.net/docs/index.html 文章目录 前言一、安装二、基本使用1. 打开bin目录的mongod.exe文件2. 基本使用的代码&#xff08;连接mongodb 服务&#xff09;3.…

【C++优先队列使用】问题总结

说明&#xff1a; 文章内容为关于priority_queue的使用总结&#xff0c;在C中要包含头文件<queue>文章内容为个人的学习整理&#xff0c;如有错误&#xff0c;欢迎指正。 文章目录 1. 优先队列默认是大根堆2. 关于优先队列和sort的比较逻辑2.1 sort的比较逻辑2.2 优先队…

【学术综述】-如何写出一篇好综述-写好综述要注意的问题

文章目录 1.前置1.1 SSD 的结构1.2 FTL的架构和作用 2 动机-why&#xff1f;3 做了什么【做了哪些方面的survey】&#xff1f;4 背景知识【上下文】5 研究的问题6 每个问题对应的解决方案 从昨天晚上【2023.11.09 22:00】到今天22:29的&#xff0c;花了一天的时间在读这篇surve…

gcc [linux]

目录 背景知识 gcc如何完成 格式 预处理&#xff08;进行宏替换&#xff09; 编译&#xff08;生成汇编&#xff09; 汇编&#xff08;生成机器可执行码&#xff09; 连接&#xff08;生成可执行文件或库文件&#xff09; 函数库 静态库 静态链接优势 动态库 动态链…

Ubuntu配置Yolov8环境并训练自己的数据集

文章目录 一、环境配置与功能测试1.1 安装1.2 目标检测1.3 实例分割1.4 分类1.5 姿态检测 二、训练数据标注三、数据集训练方法3.1 命令训练3.2 代码训练 前言&#xff1a;需要先安装CUDA和Anaconda&#xff0c;它们的安装参考我这篇文章&#xff1a;Ubuntu配置深度学习环境&am…

局域网下搭建SVN服务器

文章目录 1. 下载SVN服务器(VisualSVN Server)2. 安装SVN服务器(VisualSVN Server)3. 下载并安装TortoiseSVN4. 搭建SVN服务器 1. 下载SVN服务器(VisualSVN Server) 下载地址 2. 安装SVN服务器(VisualSVN Server) 默认安装即可 Location&#xff1a;VisualSVN Server的安装…

SpringBoot前后端分离整合cas(客户端)

SpringBoot前后端分离整合cas&#xff08;客户端&#xff09; cas认证详细流程&#xff1a; 前后端分离&#xff1a;项目前端使用nginx启动&#xff0c;后端是springBoot服务&#xff1b; nginx可以统一管理Cookie&#xff0c;避免出现跨域问题。 添加依赖 <dependency&g…

探索未来,开启无限可能:打造智慧应用,亚马逊云科技大语言模型助您一臂之力

文章目录 什么是大模型&#xff1f;大模型训练方法亚马逊云科技推出生成式AI新工具 —— aws toolkit使用教程 总结 什么是大模型&#xff1f; 近期&#xff0c;生成式大模型是人工智能领域的研究热点。这些生成式大模型&#xff0c;诸如文心一言、文心一格、ChatGPT、Stable …

strcat()用法

描述 头文件&#xff1a;<string.h>char *strcat&#xff08;char *dest&#xff0c; const char *src&#xff09;功能&#xff1a;将src字符串加到dest上&#xff0c;并返回指向dest字符串的指针。 举例 #include<stdio.h> #include<string.h> int mai…

使用非递归的方式实现归并排序

使用非递归的方式实现归并排序 话不多说&#xff0c;直接上代码&#xff1a; public class MergySort {public static void main(String[] args) {int[] nums {38, 27, 43, 3, 9, 82, 10};int[] sortedArray MergySort.mergySort(nums);// 输出排序后的数组for (int num : …

神仙打架!腾讯云阿里云谁更棋高一着?

现在&#xff0c;腾讯云和阿里云都在打价格战&#xff0c;推出了一系列的优惠政策。其中&#xff0c;腾讯云服务器只需要88元&#xff0c;而阿里云服务器也只需要99元。这么便宜的价格&#xff0c;是不是让你心动不已呢&#xff1f; 腾讯云的88元服务器&#xff1a;https://te…

CG Magic分享如何解决Vray渲染器使用不了的问题?

大家在使用Vray渲染器时&#xff0c;经常会有网友反馈说&#xff0c;为什么Vray渲染器使用不了的情况&#xff1f; vray渲染器是安装中出了问题嘛&#xff0c;还是什么原因呢&#xff1f;导致vray渲染器渲染不了。 那么&#xff0c;vray渲染器怎么安装才能正常使用呢&#xff…

java try catch 异常后还会继续执行吗

1、有 try-catch 语句块&#xff0c;并且 throw 在 catch 语句块里&#xff0c;那么 try 语句块中引发异常&#xff08;报错&#xff09;的那一行代码的后续代码都不执行并且 catch 语句块后的代码也都不执行&#xff08;遇到 finally 除外&#xff09;。&#xff08;见情形一和…

已解决:Rust Error: the trait bound is not satisfied 问题

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页: &#x1f405;&#x1f43e;猫头虎的博客&#x1f390;《面试题大全专栏》 &#x1f995; 文章图文并茂&#x1f996…

C# 同步异步大白话

同步异步大白话 背景 任务异步编程模型&#xff08;TAP&#xff09;提供了对异步代码的抽象。您可以像往常一样&#xff0c;将代码编写为一系列语句。您可以阅读该代码&#xff0c;就好像每条语句都在下一条语句开始之前完成一样。编译器执行许多转换&#xff0c;因为其中一些…

最详细的LightGBM参数介绍与深入分析

前言 我使用LightGBM有一段时间了&#xff0c;它一直是我处理大多数表格数据问题的首选算法。它有很多强大的功能&#xff0c;如果你还没有看过的话&#xff0c;我建议你去了解一下。 但我一直对了解哪些参数对性能影响最大&#xff0c;以及如何调整LightGBM参数以发挥最大作用…

使用WinDbg分析CPU100%的问题

在我们软件运行的时候&#xff0c;偶尔会出现CPU占比100%的问题&#xff0c;而且极其不容易排查&#xff0c;概率极低&#xff0c;我硬是操作了一个下午&#xff0c;出现了一次&#xff0c;然后找到了dmp文件&#xff0c;也没有任何的规律&#xff0c;那么就可以借助windbg进行…

二维码解码器怎么用?快速分解二维码图片的方法

现在很多人会将链接网址生成二维码之后来使用&#xff0c;这种方式能够让别人更快的获取链接的内容&#xff0c;而且扫码访问内容的方式也更适合大家的使用习惯。那么如果想要获取二维码中的链接时&#xff0c;一般会使用二维码解码器来处理&#xff0c;那么具体该怎么使用呢&a…

nodejs express multer 保存文件名为中文时乱码,问题解决 originalname

nodejs express multer 保存文件名为中文时乱码&#xff0c;问题解决 originalname 一、问题描述 用 express 写了个后台&#xff0c;在接收文件并保存的时候 multer 接收到的文件名为乱码。 二、解决 找了下解决方法&#xff0c;在 github 的 multer issue 中找到了答案 参…

Ubuntu 22.04 安装水星无线 USB 网卡

我的 USB 网卡是水星 Mercury 的&#xff0c; 在 Ubuntu 22.04 下面没有自动识别。 没有无线网卡的时候只能用有线接到路由器上&#xff0c;非常不方便。 寻思着把无线网卡驱动装好。折腾了几个小时装好了驱动。 1.检查网卡类型 & 安装驱动 使用 lsusb 看到的不一定是准确…