单元测试工具-Junit

文章目录

  • 一. 认识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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker进阶——再次认识docker的概念 Docker的结构 Docker镜像结构 镜像的构建方式

前言 在微服务大量应用的互联网时代&#xff0c;经常能看到docker的身影。作为docker的爱好者&#xff08;在服务器安装MySQL&#xff0c;Redis。。。我用的都是docker&#xff09;&#xff0c;我也会持续深入学习和认识docker。 本篇博客再次介绍docker的基本概念&#xff0…

SmartBear正式收购Stoplight,并计划在核心API设计、文档和门户产品中集成其功能

不久前&#xff0c;软件开发和可视化工具提供商SmartBear正式宣布收购全球领先的API设计公司Stoplight。这一收购是为了打造业内最全面的API开发平台&#xff0c;为寻求现代化API实践的开发团队提供更好的透明度、自动化与生产力。将Stoplight在API方面的优势&#xff08;包括治…

吴恩达《机器学习》7-1->7-4:过拟合问题、代价函数、线性回归的正则化、正则化的逻辑回归模型

一、过拟合的本质 过拟合是指模型在训练集上表现良好&#xff0c;但在新数据上的泛化能力较差。考虑到多项式回归的例子&#xff0c;我们可以通过几个模型的比较来理解过拟合的本质。 线性模型&#xff08;欠拟合&#xff09;&#xff1a; 第一个模型是一个线性模型&#xff0…

Elasticsearch:Lucene 中引入标量量化

作者&#xff1a;BENJAMIN TRENT 我们如何将标量量化引入 Lucene。 Lucene 中的自动字节量化 虽然 HNSW 是一种强大而灵活的存储和搜索向量的方法&#xff0c;但它确实需要大量内存才能快速运行。 例如&#xff0c;查询 768 维的 1MM float32 向量大约需要 1,000,000*4*(7681…

多维时序 | MATLAB实现TCN时间卷积神经网络多变量时间序列预测

多维时序 | MATLAB实现TCN时间卷积神经网络多变量时间序列预测 目录 多维时序 | MATLAB实现TCN时间卷积神经网络多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 MATLAB实现TCN时间卷积神经网络多变量时间序列预测 模型描述 MATLAB实现TCN时间卷…

3.前端调式(断点调式)

1. Elements 先来看这张图最上头的一行是一个功能菜单&#xff0c;每一个菜单都有它相应的功能和使用方法&#xff0c;依次从左往右来看 箭头按钮 用于在页面选择一个元素来审查和查看它的相关信息&#xff0c;当我们在Elements这个按钮页面下点击某个Dom元素时&#xff0c;箭…

ubuntu16.04安装vscode遇到的code 依赖于 libnss3 (>= 2:3.30)解决

1、ubuntu16.04安装最新版本vscode失败原因 ubuntu16.04安装最新版本的vscode会遇到依赖libnss3(>2:3.30)的问题&#xff0c;原因是ubuntu16.04安装的库libnss3版本更低&#xff0c;与vscode需要的更高版本的libnss3库不兼容&#xff0c;只需要升级libnss3库版本高于2:3.30…

PROFINET和UDP、MODBUS-RTU通信速度对比实验

这篇博客我们介绍PROFINET 和MODBUS-RTU通信实验时的数据刷新速度,以及这种速度不同对控制系统带来的挑战都有哪些,在介绍这篇对比实验之前大家可以参考下面的文章链接: S7-1200PLC和SMART PLC的PN智能从站通信 S7-200 SMART 和 S7-1200PLC进行PROFINET IO通信-CSDN博客文…

LeetCode(4)删除有序数组中的重复项 II【数组/字符串】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 80. 删除有序数组中的重复项 II 1.题目 给你一个有序数组 nums &#xff0c;请你** 原地** 删除重复出现的元素&#xff0c;使得出现次数超过两次的元素只出现两次 &#xff0c;返回删除后数组的新长度。 不要使用额外的数…

Ubuntu18.04.6安装qt5.7.1(超级详细教程)

目录 1、下载对应Linux版本的qt 2、安装完qt&#xff0c;可能也要安装下对应的编译工具 1、下载对应Linux版本的qt &#xff08;1&#xff09;准备安装的是qt5.7.1&#xff1a;qt-opensource-linux-x64-5.7.1.run &#xff08;2&#xff09;在虚拟机进入存放qt安装包的目录…

Linux安装MySQL8.0服务

Linux安装MySQL8.0服务 文章目录 Linux安装MySQL8.0服务一、卸载1.1 查看mariadb1.2 卸载 二、安装2.1 下载2.2 上传2.3 解压2.4 重命名2.5 删除2.6 创建目录2.7 环境变量2.8 修改配置2.9 配置文件2.9 用户与用户组2.10 初始化2.11 其它 三、开启远程连接MySQL 一、卸载 首先第…

springcloud图书借阅管理系统源码

开发说明&#xff1a; jdk1.8&#xff0c;mysql5.7&#xff0c;nodejs&#xff0c;idea&#xff0c;nodejs&#xff0c;vscode springcloud springboot mybatis vue elementui 功能介绍&#xff1a; 用户端&#xff1a; 登录注册 首页显示搜索图书&#xff0c;轮播图&…

地区 IP 库

地区 & IP 库 yudao-spring-boot-starter-biz-ip (opens new window)业务组件&#xff0c;提供地区 & IP 库的封装。 #1. 地区 AreaUtils (opens new window)是地区工具类&#xff0c;可以查询中国的省、市、区县&#xff0c;也可以查询国外的国家。 它的数据来自 …

MySQL | 数据库的表的增删改查【进阶】

MySQL | 数据库的表的增删改查【进阶】 文章目录 MySQL | 数据库的表的增删改查【进阶】系列文章目录本节目标&#xff1a;数据库约束约束类型NULL约束UNIQUE&#xff1a;唯一约束DEFAULT&#xff1a;默认值PRIMARY KEY&#xff1a;主键FOREIGN KEY&#xff1a;外键CHECK 表的设…

django|报错SQLite 3.8.3 or later is required的解决方案

迁移原同事写的程序&#xff0c;到新服务器上边。运行报错。解决方案有三种 降低django版本升级sqlite3&#xff0c;不低于3.8.3版本修改django源码 方案一、降低django版本 卸载高版本django pip uninstall django安装低版本&#xff0c;如 pip install django2.1.7注意&…

Linux的目录的权限

目录 目录的权限 目录的权限 1、可执行权限: 如果目录没有可执行权限, 则无法cd到目录中. 2、可读权限: 如果目录没有可读权限, 则无法用ls等命令查看目录中的文件内容. 3、可写权限: 如果目录没有可写权限, 则无法在目录中创建文件, 也无法在目录中删除文件. 上面三个权限是…

【STM32】STM32Cube和HAL库使用初体验

1.STM32Cube和HAL库模式开发流程 1、流程介绍 (1)环境搭建&#xff1a;STM32CubeMX安装、STM32xxFW安装、MDK5安装、pack包安装【顺序很重要】 【STM32】STM32的Cube和HAL生态-CSDN博客中的3.STM32CubeMX工具入门 (2)STM32CubeMX中创建工程&#xff0c;选择芯片型号&#xff0…

虚拟化服务器+华为防火墙+kiwi_syslog访问留痕

一、适用场景 1、大中型企业需要对接入用户的访问进行记录时&#xff0c;以前用3CDaemon时&#xff0c;只能用于小型网络当中&#xff0c;记录的数据量太大时&#xff0c;本例采用破解版的kiwi_syslog。 2、当网监、公安查到有非法访问时&#xff0c;可提供基于五元组的外网访…

软件测试下的AI之路(3)

&#x1f60f;作者简介&#xff1a;博主是一位测试管理者&#xff0c;同时也是一名对外企业兼职讲师。 &#x1f4e1;主页地址&#xff1a;【Austin_zhai】 &#x1f646;目的与景愿&#xff1a;旨在于能帮助更多的测试行业人员提升软硬技能&#xff0c;分享行业相关最新信息。…

【手动创建UIWindow Objective-C语言】

一、上节课,我们讲了控制器View的懒加载: 1.什么时候会调用这个懒加载呢,用我们直接,控制器self.view self.view的时候: 什么时候,调用它这个self.view, 就要去加载控制器的view, self.view 加载控制器的view 我们给大家演示过了,这个大家已经清楚了,我们给大家说…