2023.8.27 关于 Junit5 详解

news2024/11/23 7:35:01

目录

引言

注解 

断言

用例的执行顺序 

参数化

测试套件 


引言

  • Junit 是一个基于Java语言的单元测试框架
  • Selenium 是一个用于Web应用程序测试的自动化测试框架
  • 结合二者能让我们的 Web自动化测试 更加完善和全面

注意:

本文所讲的内容,均基于以下依赖,我们需自己手动引入至 pom.xml 中

<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.141.59</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>

        <!-- 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>
        </dependency>

        <!-- 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>

        <!-- 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>

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

注解 

@Test

public class JunitTest {

    @Test
    void Test01() {
        System.out.println("这是 JuniteTest 里面的 Test01");
    }
}
  • 将 @Test 注解放置在一个无参方法上,表示该方法是一个测试方法
  • 执行 JunitTest 类时,会自动执行该类中所有带有 @Test 注解的测试方法

@BeforeEach

public class JunitTest {

    @BeforeEach
    void SetUp() {
        System.out.println("这是我们BeforeEach里面的语句");
    }

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

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

该段代码执行结果:

  • @BeforeEach注解被用于标记一个方法,该方法会在每个测试方法执行之前被自动调用

@BeforeAll

public class JunitTest {

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

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

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

该段代码执行结果如下:

  • @BeforeAll 注解被用于标记一个方法,该方法会在所有测试方法执行之前被自动调用
  • @BeforeAll 注解修饰的方法必须是静态方法

@AfterEach

public class JunitTest {

    @AfterEach
    void TearDown() {
        System.out.println("这是AfterEach的语句");
    }

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

该段代码执行结果:

  • @AfterEach注解被用于标记一个方法,该方法会在每个测试方法执行之后被自动调用

@AfterAll

public class JunitTest {

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

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

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

该段代码执行结果:

  • @AfterAll 注解被用于标记一个方法,该方法会在所有测试方法执行之后被自动调用
  • @AfterAll 注解修饰的方法必须是静态方法

断言

断言是否匹配

public class JunitTest {

    @Test
    void Test09(){
        int n = 1;
//        断言是否相互匹配
        Assertions.assertEquals(2,num);
//        断言是否相互不匹配
        Assertions.assertNotEquals(2,num);
    }
}

该段代码运行结果:

  • assertEquals() 方法的第一个参数为 期望结果,第二个参数为 实际结果
  • 当 assertEquals() 方法的期望结果和实际结果不一致时,便会打印上图报错日志
  • 当 assertEquals() 方法的期望结果和实际结果一致时,便什么都不会发生,继续执行其后面的代码
  • 不难理解 assertNotEquals() 方法 跟 assertEquals() 方法 的逻辑正好相反

断言是否为真

public class JunitTest {

    @Test
    void Test09(){
        boolean b = false;
//        断言是否为真
        Assertions.assertTrue(b);
//        断言是否为假
        Assertions.assertFalse(b);
    }
}

该段代码运行结果:

  • assertTrue() 方法用来判断所给状态是否为真
  • 当 assertTrue() 方法中的状态不为真,便会打印上图报错日志
  • 当 assertTrue() 方法中的状态为真,便什么都不会发生,继续执行其后面的代码
  • 不难理解 assertFalse() 方法 跟 assertTrue() 方法 的逻辑正好相反

断言是否为空

public class JunitTest {

    @Test
    void Test09(){
//        断言是否为空
        String str = null;
        String str2 = "1";
        Assertions.assertNull(str2); //当传入 str 时 该断言不会报错
//        断言是否不为空
        Assertions.assertNotNull(str2);
    }
}

该段代码运行结果:

  • assertNull() 方法用来判断所给参数是否为 null
  • 当 assertNull() 方法中的参数不为 null,便会打印上图报错日志
  • 当 assertNull() 方法中的参数为 null,便什么都不会发生,继续执行其后面的代码
  • 不难理解 assertNotNull() 方法 跟 assertNull() 方法 的逻辑正好相反

用例的执行顺序 

一个类中默认的用例执行顺序是什么?

  • 在 Junit 框架中,默认的测试用例执行顺序是不确定的,也就是并不会按照我们所编写的用例的顺序来执行!

测试用例自定义顺序

//随机执行测试方法
//@TestMethodOrder(MethodOrderer.Random.class)
//按自定义顺序执行测试方法
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class JunitTest {

    @Order(1)
    @Test
    void A() {
        System.out.println("这是 Junite 里面的 A 测试用例");
    }

    @Order(3)
    @Test
    void B() {
        System.out.println("这是 Junite 里面的 B 测试用例");
    }
    
    @Order(2)
    @Test
    void Test01() {
        System.out.println("这是 JuniteTest 里面的 Test01");
    }

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

该段代码执行结果:

  •   @TestMethodOrder(MethodOrderer.OrderAnnotation.class) 注解 写在相应类的上方
  • 使用 @Order 注解并写在相应测试方法的上方,填写参数进行执行顺序的排序
  • @TestMethodOrder(MethodOrderer.Random.class) 注解 表示该类随机执行测试方法,不需要搭配 @Order 注解,且每次执行该类时,测试方法的执行顺序都不相同

参数化

  • 在写含有参数的测试方法时, @ParameterizedTest 注解 是必不可少的,它必须写在含参测试方法的上面,进行相应申明
  • 使用 @ParameterizedTest 注解 时,无需再加 @Test 注解

单参数

  • 单参数指的是测试方法有且仅有一个参数
public class JunitTest {

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

    @ParameterizedTest
    @ValueSource(strings = {"小","林"})
    void Test05(String str) {
        System.out.println(str);
    }
}

该段代码执行结果:

  • 该段代码 通过 @ValueSource 注释 来提供数据的来源

public class JunitTest {

    @ParameterizedTest
    @CsvFileSource(resources = "test01.csv")
    void Test06(String name) {
        System.out.println(name);
    }
}

该段代码执行结果:

  • 该段代码通过 @CsvFileSource 注释 来提供数据的来源 (适用于有大量测试用例的情况)

使用 @CsvFileSource 注释 的 操作步骤:

1. 在 resources 文件夹下创建后缀名为 .csv 的文件

2.在 @CsvFileSource 注解中,写上新创建的文件名字

 3.点开新创建的文件,进行数据编写,每行代表 一个 name 参数,传入测试方法中

 


多参数

public class JunitTest {

    @ParameterizedTest
    @CsvSource({"1, 2, ''"}) // z 为一个空字符串且能被打印
    void Test08(String x,String y,String z) {
        System.out.println(x);
        System.out.println(y);
        System.out.println(z);
        System.out.println("======================");
    }

    @ParameterizedTest
    @CsvSource({"小林,18", "小王,20"}) 
    void Test10(String name, String age) {
        System.out.println(name +" " + age);
    }
}

该段代码执行结果:

  •   该段代码 通过 @CsvSource 注释 来提供数据的来源
  • @CsvSource 注释中的 每一个双引号就是一组参数

动态参数

public class JunitTest {

    @ParameterizedTest
    @MethodSource("Generator")//相匹配的方法必须为静态方法
    void Test07(String str, int num) {
        System.out.println(str + ":" + num);
    }
    /*
        注意:
        1.首先方法必须为 静态方法
        2.如果返回的数据类型时同一的,直接写该具体类型
          如果不统一,需要使用组合类型 Arguments
    */
    public static Stream<Arguments> Generator() throws InterruptedException {
        String[] arr = new String[3];
        for (int i = 0; i < 3; i++) {
//            这里加上 强制等待 是因为 该循环执行速度太快 时间戳 变化不明显 
            sleep(500);
            arr[i] = System.currentTimeMillis() + "";
        }
        return Stream.of(Arguments.arguments(arr[0],1),
                Arguments.arguments(arr[1],2),
                Arguments.arguments(arr[2],3));
    }
}

该代码执行结果:

  • 该段代码 通过 @MethodSource 注释 来提供数据的来源
  • 作为动态参数我们可以写一个包含时间戳的静态方法来创建变化的数据
  • 静态方法作为数据源的同时,也是 @MethodSource 注释 的参数

测试套件 

指定类名来运行类下的所有用例

JuniteTest 类:

public class JunitTest {

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

JuniteTest2 类:

public class JunitTest2 {

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

RunSuite 类:

@Suite
//这里的测试用例类 按照我们所写的 class 的一个顺序来进行执行的
@SelectClasses({JunitTest.class,JunitTest2.class})
public class RunSuite {
}

该段代码执行结果: 

  • 新创建一个 RunSuite 类
  • 通过 @Suite 注解 声明该类为测试套件类(不是测试类)
  • 我们便可通过 @SelectClasses 注解来自定义 测试类的执行顺序
  • 所运行的测试方法 必须使用 @Test 注解

指定包名来运行包下的所有用例

package01 包:

package package01;

public class Test01 {

    @Test
    void test01() {
        System.out.println("这是 包:package01 类:Test01 中的 test01 方法");
    }
}

package02 包:

package package02;

import org.junit.jupiter.api.Test;

public class Test02 {
    @Test
    void test02(){
        System.out.println("这是 包:package02 类:Test02 中的 test02 方法");
    }
}

RunSuite 类:

@Suite
//这里的测试用例类 按照我们所写的 package 的一个顺序来进行执行的
@SelectPackages(value = {"package02", "package01"})
public class RunSuite {
}

该段代码执行结果: 

  • 新创建一个 RunSuite 类
  • 通过 @Suite 注解 声明该类为测试套件类(不是测试类)
  • 我们便可通过 @SelectPackages 注解来自定义 测试类的执行顺序

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

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

相关文章

机器视觉工程师永不为奴,他们是肯干肯出差肯加班肯拼命肯被使唤肯被叼

​ 永不为奴&#xff0c;为什么这样呐喊&#xff0c;真的很难做到。我们职业机器视觉工程师&#xff0c;本身职业具有一大特点就是专业性。 但是我们机器视觉工程师是专业技术绝不苟同于不是技术人员言语&#xff0c;我们很专业。 肯出差&#xff1a; 设备去那里&#xff0c;…

启莱OA CloseMsg.aspx SQL注入

子贡曰&#xff1a;“贫而无谄&#xff0c;富而无骄&#xff0c;何如&#xff1f;”子曰&#xff1a;“可也。未若贫而乐&#xff0c;富而好礼者也。” 子贡曰&#xff1a;“《诗》云&#xff1a;‘如切如磋&#xff0c;如琢如磨。’其斯之谓与&#xff1f;”子曰&#xff1a;“…

mybatis plus新版代码生成器,类型转换处理器ITypeConvertHandler使用

目录 引言关键代码源码分析记录一坑类型转换的第二种方式完整源码地址 引言 当默认生成的数据类型不满足时&#xff0c;就需要自定义指定要生成的类型 关键代码 FastAutoGenerator.create(url, username, password).dataSourceConfig(builder -> {builder.typeConvertHandl…

Python计算加速利器

迷途小书童的 Note 读完需要 6分钟 速读仅需 2 分钟 1 简介 Python 是一门应用非常广泛的高级语言&#xff0c;但是&#xff0c;长久以来&#xff0c;Python的运行速度一直被人诟病&#xff0c;相比 c/c、java、c#、javascript 等一众高级编程语言&#xff0c;完全没有优势。 那…

记一次因函数入参没有带类型所引发的问题

工作中&#xff0c;sit测试中&#xff0c;测试突然发现页面异常。经排查&#xff0c;是函数参数没有定义类型所以&#xff0c;dart默认是dynamic类型&#xff0c;而dynamic编译阶段不检查类型&#xff0c;正是由于编译阶段不检查类型&#xff0c;很明显的错误也只能运行的时候才…

【Axure高保真原型】中继器网格图片拖动摆放

今天和大家分享中继器网格图片拖动摆放的原型模板&#xff0c;我们可以通过鼠标拖动来移动图片&#xff0c;拖动过程其他图标会根据图片拖动自动排列&#xff0c;松开鼠标是图片停放在指定位置&#xff0c;其他图标自动排列。那这个模板是用中继器制作的&#xff0c;所以使用也…

C# 跨线程访问窗体控件

在不加任何修饰的情况下&#xff0c;C# 默认不允许跨线程访问控件&#xff0c;实际在项目开发过程中&#xff0c;经常使用跨线程操作控件属性&#xff0c;需要设置相关属性才能正确使用&#xff0c;两种方法设置如下&#xff1a; 方法1&#xff1a;告诉编译器取消跨线程访问检…

XML—标记语言

什么是XML&#xff1f; Extensible Markup Language&#xff0c;可扩展标记语言。 那标记语言是什么&#xff1f; 用文字做标记表达一些效果或携带一些数据。比如&#xff1a;HTML、XML 我的理解&#xff1a;用倾盆大雨表达雨很大 那XML为什么说是可扩展的呢&#xff1f; 还…

ethers.js9、过滤事件

在 合约监听 的基础上,我们拓展一下,在监听的过程中增加过滤器,监听指定地址的转入转出。 过滤器 当合约创建日志(释放事件)时,它最多可以包含[4]条数据作为索引(indexed)。索引数据经过哈希处理并包含在布隆过滤器中,这是一种允许有效过滤的数据结构。因此,一个事件…

Java学数据结构(4)——散列表Hash table 散列函数 哈希冲突

目录 引出散列表Hash table关键字Key和散列函数(hash function)散列函数解决collision哈希冲突&#xff08;碰撞&#xff09;分离链接法(separate chaining)探测散列表(probing hash table)双散列(double hashing) Java标准库中的散列表总结 引出 1.散列表&#xff0c;key&…

SQLite数据库C_C++接口(保姆级API应用 1.4W字)(全网最详细介绍,学完必掌握)

目录 sqlite3的C/C API应用 前言 SQLite3库安装 API函数 打开、关闭、错误处理 打开 返回值 关闭 错误调试 实际应用 执行SQL&#xff08;DDL、DML&#xff09; API介绍 实际应用 回调函数查询 API介绍 实际应用 全缓冲查询 API介绍 实际应用 字节缓冲查询…

【Linux】【驱动】自动创建设备节点

【Linux】【驱动】自动创建设备节点 续驱动代码操作指令linux端从机端 续 这里展示了如何自动的方式去创建一个字符类的节点 下面就是需要调用到的程序 函数 void cdev_init(struct cdev *, const struct file_operations *);第一个参数 要初始化的 cdev 第二个参数 文件操作…

【微服务部署】01-Kubernetes部署流程

文章目录 部署1. Kubernetes是什么2. Kubernetes的优势3. 环境搭建4. 应用部署 部署 1. Kubernetes是什么 Kubernetes是一个用于自动部署、扩展和管理容器化应用程序的开源系统 2. Kubernetes的优势 自动化容器部署资源管理与容器调度服务注册发现与负载均衡内置配置与秘钥…

STM32 CUBEMX CAN通信数据发送失败原因分析

CAN通信是一种数据通信协议&#xff0c;用于在不同设备之间进行通信。它是一种高效的、实时的、可靠的、多主机的、串行通信系统&#xff0c;通常用于汽车电子、工业自动化等领域。CAN通信协议是由德国BOSCH公司于1986年引入&#xff0c;并在欧洲和日本广泛使用。CAN通信具有独…

uniapp热更新

首先热更新需要wgt包&#xff1b; 其次先了解这两个组件 下载的方法 安装的组件 场景&#xff1a; 当你项目的js文件或者页面文件或者静态图片文件css文件更新的时候可以走热更新&#xff1b; 而当你安装新的组件插件或者开启新的权限等功能的时候就无法通过热更新进行更新了…

自然语言处理(三):基于跳元模型的word2vec实现

跳元模型 回顾一下第一节讲过的跳元模型 跳元模型&#xff08;Skip-gram Model&#xff09;是一种用于学习词向量的模型&#xff0c;属于Word2Vec算法中的一种。它的目标是通过给定一个中心词语来预测其周围的上下文词语。 这节我们以跳元模型为例&#xff0c;讲解word2vec的…

C语言(第三十四天)

1. 二进制 其实我们经常能听到2进制、8进制、10进制、16进制这样的讲法&#xff0c;那是什么意思呢&#xff1f;其实2进制、8进制、10进制、16进制是数值的不同表示形式而已。 比如&#xff1a;数值15的各种进制的表示形式: 15的2进制&#xff1a;1111 15的8进制&#xff1a;1…

开源项目的文档:为什么它如此重要?

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

2023.8.28日论文阅读

文章目录 NestFuse: An Infrared and Visible Image Fusion Architecture based on Nest Connection and Spatial/Channel Attention Models(2020的论文)本文方法 LRRNet: A Novel Representation Learning Guided Fusion Network for Infrared and Visible Images本文方法学习…

JVM 内存大对象监控和优化实践

作者&#xff1a;vivo 互联网服务器团队 - Liu Zhen、Ye Wenhao 服务器内存问题是影响应用程序性能和稳定性的重要因素之一&#xff0c;需要及时排查和优化。本文介绍了某核心服务内存问题排查与解决过程。首先在JVM与大对象优化上进行了有效的实践&#xff0c;其次在故障转移与…