Junit5基础教程

news2024/12/30 4:04:38

Junit5的构成:

  • Junit Platform+Junit Jupiter+Junit Vintage
  • Junit Platform:是Junit向测试平台演进,提供平台功能的模块,通过这个其他的自动化引擎可以接入Junit,实现对接和执行
  • Junit Jupiter:核心,承载Juint4原有功能+丰富的新特性
  • Junit Vintage:主要功能是对Juint旧版本进行兼容

一,导入依赖

 <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <junit-platform.version>1.8.1</junit-platform.version>
        <junit-jupiter.version>5.8.1</junit-jupiter.version>
    </properties>
    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>3.0.0-M5</version>
                    <dependencies>
                        <dependency>
                            <groupId>org.junit.jupiter</groupId>
                            <artifactId>junit-jupiter-engine</artifactId>
                            <version>5.8.1</version>
                        </dependency>
                    </dependencies>
                    <configuration>
                        <includes>
                            <include>**/*Test.java</include>
                        </includes>
                    </configuration>
                </plugin>

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                    <configuration>
                        <source>1.8</source>
                        <target>1.8</target>
                    </configuration>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
  <!--核心依赖-->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.8.1</version>
        </dependency>
        <!--套件测试使用-->
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-runner</artifactId>
            <version>1.8.1</version>
        </dependency>
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-runner</artifactId>
            <version>1.8.1</version>
        </dependency>

二,基本功能

一、常用断言

在这里插入图片描述

二、执行顺序和常用注解

1、通过BeforeAll类的注解来保证顺序
// 执行顺序:beforeAll-beforeEach-afterEach-afterAll
@DisplayName("常用注解测试")
public class TestCase {
    /**
     * @BeforeAll和@AfterAll 必须静态修饰,在所有方法执行前后只执行一次
     * @Test 一个方法
     * @AfterEach和@BeforeEach 每次方法执行前都会执行一次
     * @DisplayName() 类似注解的功能
     * @RepeatedTest(5) 重复5次
     * @Disabled 不执行该方法
     * @Tags 打标签
     */
    @BeforeAll
    public static void beforeAll() {
        System.out.println("BeforeAll再每个类中只执行一次,且是在开头执行");
    }

    @BeforeEach
    public void beforeEach() {
        System.out.println("BeforeEach在每个方法执行前都会执行一次");
    }

    // junit5不需要访问修饰符
    //  @Disabled表示不执行
    @Test
    @Disabled
    @DisplayName("方法1")
    void fun1() {
        System.out.println("---fun1---");
    }

    @Test
    @DisplayName("方法2")
    @RepeatedTest(5)
    void fun2() {
        System.out.println("---fun2---");
    }

    @Test
    @Tag("tag1")
    void tagTest(){
        System.out.println("tag1");
    }
    @AfterEach
    public void afterEach() {
        System.out.println("AfterEach在每个方法执行前都会执行一次");
    }

    @AfterAll
    public static void afterAll() {
        System.out.println("afterAll再每个类中只执行一次,且是在结尾执行");
    }
}

2、通过order注解来保证执行顺序
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
 
@TestMethodOrder(OrderAnnotation.class)
class OrderedTestsDemo {
 
  @Test
  @Order(1)
  void nullValues() {
      // perform assertions against null values
  }
 
  @Test
  @Order(2)
  void emptyValues() {
      // perform assertions against empty values
  }
 
  @Test
  @Order(3)
  void validValues() {
      // perform assertions against valid values
  }
}
  • allure注解
    在这里插入图片描述

三、依赖测试

/**
 * @Nested:
 * 功能类似于suite测试套件
 * 从下往上执行
 */

public class NestedTest {
    private static HashMap<String, Object> dataMap = new HashMap<String, Object>();

    @Test
    void login() {
        dataMap.put("login", "登录成功");
    }

    @Nested
    class Shopping{
        @Test
        void shopping(){
            if (null!=dataMap.get("buy")){
                System.out.println("购买成功啦!");
            }else {
                System.out.println("购买失败");
            }
        }
    }

    @Nested
    class Buy {
        @Test
        void buyTest() {
            if (dataMap.get("login").equals("登录成功")) {
                System.out.println("登录成功");
                dataMap.put("buy", "登录成功,快去购物吧!");
            } else {
                System.out.println("登录失败");
            }
        }
    }
}

四、参数化测试

写过一篇,点这里!!

五、测试套件

SelectPackages、IncludePackages、SelectClasses、IncludeTags等注解的使用
/**
 * SelectPackages 选择需要执行的包
 */
@RunWith(JUnitPlatform.class)
@SelectPackages({"com.testCase2"})
public class SelectPackagesTest {

}
/**
 * @IncludePackages需要和@SelectPackages搭配使用
 * @IncludePackages是在@SelectPackages的基础上再做一层筛选
 * ps:一定要注意,包下的类名一定要Test开头或者结尾,否则就不执行了!!!
 */
@RunWith(JUnitPlatform.class)
@SelectPackages({"com.testCase2"})
// 只执行com.testCase2.demo1
@IncludePackages({"com.testCase2.demo1"})
public class IncludePackagesTest {
}
/**
 * @SelectClasses和@IncludeTags组合使用,在方法里选出对应的标签
 * 还有@ExcludeTag
 */
@RunWith(JUnitPlatform.class)
@SelectClasses({TestCase.class})
//@IncludeTags("tag1")
@ExcludeTags("tag1")
public class SelectClassesTest {
}

六、软断言

  • assertAll断言方法,会在执行完所有断言后统⼀输出结果,⼀次性暴露所有问题,提高了测试脚本的健壮性。
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.function.Executable;

import java.util.ArrayList;
import java.util.List;

import static org.junit.jupiter.api.Assertions.assertAll;

public class AssertAllDemo {
    // 普通方法,第一个执行失败以后后面都不执行
    @Test
    void assertTest1() {
        Assertions.assertTrue(2 == 1);
    }

    void assertTest2() {
        Assertions.assertTrue(3 == 1);
    }

    void assertTest3() {
        Assertions.assertTrue(1 == 1);
    }

    // 用了assertAll之后,所有方法都执行
    @Test
    void assertAllTest() {
        assertAll(
                "多次结果校验",
                () -> {
                    Assertions.assertTrue(2 == 1);
                },
                () -> {
                    Assertions.assertTrue(3 == 1);
                }
        );
    }

    @Test
    void assertAllTtest02() {
        List<Executable> assertList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            int result = i;
            System.out.println(result);
            assertList.add(() -> {
                Assertions.assertEquals(10, result);
            });
        }
        assertAll("多次结果校验", assertList.stream());
    }

}

七、并发测试

  • 测试环境基本上都是单线程操作,而线上存在分布式的并发场景,所以并不能暴露所有问题,这里就需要用到并发
  • junit测试是在⼀个线程中串行执行的,从5.3开始⽀持并行测试。⾸先需要在配置⽂件junit-platform.properties 中配置。
#是否允许并行执行true/false
junit.jupiter.execution.parallel.enabled = true
#是否支持方法级别多线程same_thread/concurrent
junit.jupiter.execution.parallel.mode.default = concurrent
#是否支持类级别多线程same_thread/concurrent
junit.jupiter.execution.parallel.mode.classes.default = concurrent
# the maximum pool size can be configured using a ParallelExecutionConfigurationStrategy
junit.jupiter.execution.parallel.config.strategy=fixed
junit.jupiter.execution.parallel.config.fixed.parallelism=4

import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;

/**
 * 并发测试
 */
public class ParallelTest {
  static   int result = 0;

    // 加synchronized可以保证其原子性,但是如果是分布式系统是不适合的,需要用如redis分布式锁
    public static  int cal(int x) throws InterruptedException {
        int i = result;
        Thread.sleep(1000);
        result = i + x;
        return result;
    }
    public static int add(int x,int y) throws InterruptedException {
        Thread.sleep(1000);
        result = y + x;
        return result;
    }
    @RepeatedTest(10)
    public void testCal() throws InterruptedException {
        long id = Thread.currentThread().getId();
        System.out.println("线程" + id + "为你服务:" + cal(1));
    }
    @RepeatedTest(10)
    public void testAdd() throws InterruptedException {
        long id = Thread.currentThread().getId();
        System.out.println("加法计算:线程" + id + "为你服务:" + add(1,2));
    }
}

八、动态测试解决硬编码问题

  • 传统自动化测试思路中,我们的测试逻辑是在以硬编码的形式组织到代码里的,当遇到用例迁移或结果整合时,会产生大量的逻辑重写
  • JUnit5提供了动态测试方案,让测试人员可以在脚本Runtime时动态的批量生成用例
  • 现在我们有一个需求,要把yaml文件内容转为测试用例,解决思路如下:
    在这里插入图片描述
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestFactory;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * 动态测试demo
 * 需求:把result.yaml脚本变成测试用例
 * 首先把它通过反序列化变成对象
 * 然后把它添加到dynamicTestList
 */
public class ShellTestResult {
        @TestFactory
    Collection<DynamicTest> shellTestResult() throws IOException {
        // 新建一个列表来存储数据(不是结果)
        List<DynamicTest> dynamicTestList = new ArrayList<>();
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        // 反序列化方式把yaml文件转换为对象列表
        ResultList resultList = mapper.readValue(new File("D:\\interface_auto\\src\\main\\resources\\result.yaml"), ResultList.class);
        System.out.println("done");
        // 动态遍历生成测试方法
        for (Result result : resultList.getResultList()) {
            // 把数据收集起来
            dynamicTestList.add(
                    // 动态生成测试方法
                    DynamicTest.dynamicTest(result.getCaseName(), () -> {
                        Assertions.assertTrue(result.isResult());
                    })
            );
        }
        return dynamicTestList;
    }
}

import lombok.Data;

@Data
public class Result {
    private String caseName;
    private boolean result;

    public boolean isResult() {
        return result;
    }

    public void setResult(boolean result) {
        this.result = result;
    }
}
@Data
public class ResultList {
    private List<Result> resultList;
}

九、Junit5启动类(适用于持续集成)

import org.junit.platform.launcher.Launcher;
import org.junit.platform.launcher.LauncherDiscoveryRequest;
import org.junit.platform.launcher.TestExecutionListener;
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
import org.junit.platform.launcher.core.LauncherFactory;
import org.junit.platform.launcher.listeners.SummaryGeneratingListener;

import static org.junit.platform.engine.discovery.ClassNameFilter.includeClassNamePatterns;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectPackage;

/**
 * junit5启动类(适用于持续集成这种点不了执行的)
 */
public class LauncherDemo {
    public static void main(String[] args) {
        LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request().selectors(
                // 2个过滤条件是or不是and:
                selectPackage("com.learn.junit5"),
                selectClass(TestExecutionOrder.class)
        ).filters(
//                includeClassNamePatterns("Test.*")
        )
                .build();
        Launcher launcher = LauncherFactory.create();
        TestExecutionListener listener = new SummaryGeneratingListener();
        launcher.registerTestExecutionListeners(listener);
        launcher.execute(request);
    }
}

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

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

相关文章

javaweb物业管理系统jsp项目

文章目录 物业管理系统一、系统演示二、项目介绍三、系统部分功能截图四、部分代码展示五、底部获取项目源码&#xff08;9.9&#xffe5;带走&#xff09; 物业管理系统 可用作javaweb项目、servlet项目、jsp项目的项目设计 一、系统演示 物业管理系统 二、项目介绍 语言&a…

春晚魔术和约瑟夫问题

春晚的魔术实际上是一个约瑟夫问题&#xff0c;最终的结果是魔术开始时确定的几个变量确定好的&#xff0c;扑克牌只是道具和障眼法。网上一查这个问题发现颇有历史渊源&#xff0c;17世纪的法国数学家加斯帕在《数目的游戏问题》中讲了这样一个故事&#xff1a;15个教徒和15 个…

酷开科技荣获“消费者服务之星”称号后的未来展望

恭喜酷开科技荣获2023年第四季度黑猫平台“消费者服务之星”称号&#xff01;这是对酷开科技长期以来坚持用户至上、用心服务的肯定和认可。作为OTT行业的佼佼者&#xff0c;酷开科技一直秉承着“以用户为中心”的服务理念&#xff0c;不断追求卓越品质&#xff0c;为用户提供更…

《CSS 简易速速上手小册》第6章:高级 CSS 技巧(2024 最新版)

文章目录 6.1 使用 CSS 变量进行设计&#xff1a;魔法配方的调配6.1.1 基础知识6.1.2 重点案例&#xff1a;创建可定制的主题6.1.3 拓展案例 1&#xff1a;响应式字体大小6.1.4 拓展案例 2&#xff1a;使用 CSS 变量创建动态阴影效果 6.2 calc(), min(), max() 等函数的应用&am…

Java 基于微信小程序的电子商城购物系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

使用R语言fifer包进行分层采样

使用R语言fifer包中的stratified()函数用来进行分层采样非常方便&#xff0c;但fifer包已经从CRAN存储库中删除&#xff0c;需要从存档中下载可用的历史版本&#xff0c;下载链接&#xff1a;Index of /src/contrib/Archive/fifer (r-project.org)https://cran.r-project.org/s…

架构篇34:深入理解微服务架构 - 银弹 or 焦油坑?

文章目录 微服务与 SOA 的关系微服务的陷阱小结 微服务是近几年非常火热的架构设计理念&#xff0c;大部分人认为是 Martin Fowler 提出了微服务概念&#xff0c;但事实上微服务概念的历史要早得多&#xff0c;也不是 Martin Fowler 创造出来的&#xff0c;Martin 只是将微服务…

Github 2024-02-11 开源项目日报Top10

根据Github Trendings的统计&#xff0c;今日(2024-02-11统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目4非开发语言项目2C项目1C项目1Solidity项目1JavaScript项目1Rust项目1HTML项目1 免费服务列表 | f…

KingSCADA实现按钮点击效果

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 在做SCADA项目的时候&#xff0c;按钮是不可缺少的功能&#xff0c;但软件自带的按钮太丑&#xff0c;已经无法满足现如今客户对界面美观度的要求。 这时候就需要UI小姐姐设计美观大气的SCADA界面&#xff0c;但UI设计…

内网安全-内网穿透

目录 内网渗透 Nc使用详解 Nc监听和探测 Nc传文件 termite内网穿透工具 ssh代理内网穿透 ssh配置socket代理 MSF多级网络穿透 内网渗透 Nc使用详解 Nc监听和探测 Nc传文件 termite内网穿透工具 1、termite 之前叫ew &#xff08;可以进行正向连接&#xff0c;可以…

[ai笔记3] ai春晚观后感-谈谈ai与艺术

欢迎来到文思源想的ai空间&#xff0c;这是技术老兵重学ai以及成长思考的第3篇分享&#xff01; 今天我们不聊技术&#xff0c;只聊感受&#xff01; 1 关于ai春晚 期待许久的ai春晚&#xff0c;但是等初一晚上观看的时候&#xff0c;或多或少还是有些失望。 首先是观看人数…

【java】笔记10:类与对象——本章练习

题目1&#xff1a; 代码如下&#xff1a; import java.util.Scanner; public class Input{public static void main(String[]args){Circle cnew Circle();PassObject yuannew PassObject();System.out.println("r""\t""times");yuan.printAreas…

Linux操作系统基础(九):Linux用户与权限

文章目录 Linux用户与权限 一、文件权限概述 二、终端命令&#xff1a;组管理 三、终端命令&#xff1a;用户管理 1、创建用户 、 设置密码 、删除用户 2、查看用户信息 3、su切换用户 4、sudo 4.1、给指定用户授予权限 4.2、使用 用户 zhangsan登录, 操作管理员命令…

HTTP网络通信协议基础

目录 前言&#xff1a; 1.HTTP协议理论 1.1协议概念 1.2工作原理 2.HTTP抓包工具 2.1Fiddler工具 2.2抓包原理 3.HTTP协议格式 3.1HTTP请求 3.2HTTP响应 3.3格式总结 前言&#xff1a; 在了解完网络编程的传输层UDP和TCP通信协议后&#xff0c;就需要开始对数据进行…

Netty应用(六) 之 异步 Channel

目录 12.Netty异步的相关概念 12.1 异步编程的概念 12.2 方式1&#xff1a;主线程阻塞&#xff0c;等待异步线程完成调用&#xff0c;然后主线程发起请求IO 12.3 方式2&#xff1a;主线程注册异步线程&#xff0c;异步线程去回调发起请求IO 12.4 细节注释 12.5 异步的好处…

【Android】使用Android Studio运行Hello World项目

文章目录 1. JDK的安装与配置2. Android Studio的安装3. 运行Hello World项目3.1 新建项目3.2 修改项目配置3.2.1 修改UI界面3.2.2 配置 Android SDK 3.3 添加并运行虚拟设备3.4 运行项目 1. JDK的安装与配置 想要使用Android Studio&#xff0c;必须先配置Java环境&#xff0…

机器学习之监督学习和非监督学习

监督学习(Supervised Learning)监督学习是一种学习方式&#xff0c;其中模型从标记的训练数据中学习。这意味着每个训练样本都是由输入向量和相应的目标输出(也称为标签)组成的。模型的任务是学习输入到输出的映射函数&#xff0c;以便当提供新的、未见过的数据时&#xff0c;模…

MyBatis中#和$符的区别,sql注入问题,动态sql语句

MyBatis中#{}和${}的区别 #{}和${}都是MyBatis提供的sql参数替换。区别是&#xff1a;#{}是预编译处理&#xff0c;${}是字符串直接替换。#{}可以防止SQL注入&#xff0c;${}存在SQL注入的风险&#xff0c;例如 “ or 11”虽然存在SQL注入风险&#xff0c;但也有自己的适用场…

CSS Selector—选择方法,和html自动——异步社区的爬取(动态网页)——爬虫(get和post的区别)

这里先说一下GET请求和POST请求&#xff1a; post我们平时是要加data的也就是信息&#xff0c;你会发现我们平时百度之类的 搜索都是post请求 get我们带的是params&#xff0c;是发送我们指定的内容。 要注意是get和post请求&#xff01;&#xff01;&#xff01; 先说一下异…

python基于flask的网上订餐系统769b9-django+vue

课题主要分为两大模块&#xff1a;即管理员模块和用户模块&#xff0c;主要功能包括个人中心、用户管理、菜品类型管理、菜品信息管理、留言反馈、在线交流、系统管理、订单管理等&#xff1b; 如果用户想要交换信息&#xff0c;他们需要满足双方交换信息的需要。由于时间有限…