欢送拜访我的GitHub
https://github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套源码,波及Java、Docker、Kubernetes、DevOPS等;
对于《JUnit5学习》系列
《JUnit5学习》系列旨在通过实战晋升SpringBoot环境下的单元测试技能,一共八篇文章,链接如下:
- 基本操作
- Assumptions类
- Assertions类
- 按条件执行
- 标签(Tag)和自定义注解
- 参数化测试(Parameterized Tests)根底
- 参数化测试(Parameterized Tests)进阶
- 综合进阶(终篇)
本篇概览
本文是《JUnit5学习》系列的第五篇,一起来学习JUnit5的标签(Tag)性能,构想一个工程中的有很多测试类和测试方法,有的场景只需执行其中一部分测试方法,如何实现呢?此时Junit的标签性能就派上用场了,咱们能够按须要给测试类或者办法打标签,在执行单元测试时依照标签进行过滤,学完了标签再来理解JUnit5对自定义注解的反对状况,本篇纲要如下:
- 设置标签
- 在IDEA中做标签过滤
- 用maven命令时做标签过滤
- 用surefire插件时做标签过滤
- 标签表达式
- 自定义注解
- 更加简化的自定义注解
- 标签命名标准
源码下载
- 如果您不想编码,能够在GitHub下载所有源码,地址和链接信息如下表所示:
名称 | 链接 | 备注 |
---|---|---|
我的项目主页 | https://github.com/zq2599/blo... | 该我的项目在GitHub上的主页 |
git仓库地址(https) | https://github.com/zq2599/blo... | 该我的项目源码的仓库地址,https协定 |
git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该我的项目源码的仓库地址,ssh协定 |
- 这个git我的项目中有多个文件夹,本章的利用在<font color="blue">junitpractice</font>文件夹下,如下图红框所示:
- <font color="blue">junitpractice</font>是父子构造的工程,本篇的代码在<font color="red">tag</font>子工程中,如下图:
设置标签
- 在父工程<font color="blue">junitpractice</font>里新建名为<font color="blue">tag</font>的子工程,明天的单元测试代码都写在这个tag工程中;
- 一共写两个测试类,第一个FirstTest.java如下,可见类上有Tag注解,值为<font color="blue">first</font>,另外每个办法上都有Tag注解,其中<font color="blue">first1Test</font>办法有两个Tag注解:
package com.bolingcavalry.tag.service.impl;import lombok.extern.slf4j.Slf4j;import org.junit.jupiter.api.DisplayName;import org.junit.jupiter.api.Tag;import org.junit.jupiter.api.Test;import org.springframework.boot.test.context.SpringBootTest;import static org.junit.jupiter.api.Assertions.assertEquals;@SpringBootTest@Slf4j@Tag("first")public class FirstTest { @Test @Tag("easy") @Tag("important") @DisplayName("first-1") void first1Test() { log.info("first1Test"); assertEquals(2, Math.addExact(1, 1)); } @Test @Tag("easy") @DisplayName("first-2") void first2Test() { log.info("first2Test"); assertEquals(2, Math.addExact(1, 1)); } @Test @Tag("hard") @DisplayName("first-3") void first3Test() { log.info("first3Test"); assertEquals(2, Math.addExact(1, 1)); }}
- 第二个测试类SecondTest.java,也是类和办法都有Tag注解:
package com.bolingcavalry.tag.service.impl;import lombok.extern.slf4j.Slf4j;import org.junit.jupiter.api.DisplayName;import org.junit.jupiter.api.Tag;import org.junit.jupiter.api.Test;import org.springframework.boot.test.context.SpringBootTest;import static org.junit.jupiter.api.Assertions.assertEquals;@SpringBootTest@Slf4j@Tag("second")public class SecondTest { @Test @Tag("easy") @DisplayName("second-1") void second1Test() { log.info("second1Test"); assertEquals(2, Math.addExact(1, 1)); } @Test @Tag("easy") @DisplayName("second-2") void second2Test() { log.info("second2Test"); assertEquals(2, Math.addExact(1, 1)); } @Test @Tag("hard") @Tag("important") @DisplayName("second-3") void second3Test() { log.info("second3Test"); assertEquals(2, Math.addExact(1, 1)); }}
- 以上就是打好了标签的测试类和测试方法了,接下来看看如何通过这些标签对测试方法进行过滤,执行单元测试有三种罕用形式,咱们挨个尝试每种形式如何用标签过滤;
在IDEA中做标签过滤
- 如下图所示,点击红框中的<font color="blue">Edit Configurations...</font>:
- 如下图红框,在弹出的窗口上新增一个JUnit配置:
- 接下来的操作如下图所示,<font color="blue">Test kind</font>抉择<font color="red">Tags</font>,就会依照标签过滤测试方法,<font color="blue">Tag expression</font>外面填写过滤规定,前面会具体解说这个规定,这里先填个已存在的标签<font color="red">important</font>:
- 创立好JUnit配置后,执行下图红框中的操作即可执行单元测试:
- 执行后果如下,所有打了<font color="blue">important</font>标签的测试方法被执行:
用maven命令时做标签过滤
- 前面试过IDEA上按标签过滤测试方法,其实用maven命令执行单元测试的时候也能按标签来过滤,接下来试试;
- 在父工程<font color="blue">junitpractice</font>的pom.xml所在目录下,执行以下命令,即可开始单元测试,并且只执行带有标签的办法:
mvn clean test -Dgroups="important"
- 执行结束后后果如下:
- 翻看日志,可见只有打了important标签的测试方法被执行了,如下图红框所示:
- 再看看其余子工程的执行状况,用前一篇文章里的conditional为例,可见没有任何测试方法被执行,如下图红框所示:
- 再去看看surefire插件给出的测试报告,报告文件在<font color="blue">junitpractice\tag\target\surefire-reports</font>目录下,下图红框中的文件就是测试报告:
- 关上上图红框中的一个文件,如下图红框,可见只有打了<font color="blue">important</font>标签的测试方法被执行了:
- 以上就是maven命令执行单元测试时应用标签过滤的办法,接下来试试在应用maven-surefire-plugin插件时如何通过做标签过滤
用surefire插件时做标签过滤
- surefire是个测试引擎(TestEngine),以maven插件的形式来应用,关上tag子工程的pom.xml文件,将build节点配置成以下模式,可见groups就是标签过滤节点,另外<font color="blue">excludedGroups</font>节点制订的hard标签的测试方法不会执行:
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.2</version> <configuration> <!--要执行的标签--> <groups>important</groups> <!--不要执行的标签--> <excludedGroups>hard</excludedGroups> </configuration> </plugin> </plugins> </build>
- 在tag子工程的pom.xml所在目录,执行命令<font color="blue">mvn clean test</font>即可开始单元测试,后果如下,可见打了important标签的first1Test被执行,而second3Test办法只管有important标签,然而因为其hard标签曾经被设置为不执行,因而second3Test没有被执行:
标签表达式
- 后面咱们用三种办法执行了单元测试,每次都是用important标签过滤,其实除了指定标签,JUnit还反对更简单的标签过滤,即标签表达式
- 所谓标签表达式,就是用"非"、"与"、"或"这三种操作符将更多的标签连接起来,实现更简单的过滤逻辑;
- 上述三种操作符的定义和用法如下表:
操作符 | 作用 | 举例 | 举例说明 | ||
---|---|---|---|---|---|
& | 与 | important & easy | 既有important,又有easy标签, 在本文是first1Test | ||
! | 非 | important & !easy | 有important,同时又没有easy标签, 在本文是second3Test | ||
\ | 或 | important \ | hard | 有important标签的,再加上有hard标签的, 在本文是first1Test、first3Test、second3Test |
- 试试标签表达式的成果,如下图红框,批改后面创立好的IDEA配置,从之前的<font color="blue">important</font>改为<font color="red">important | hard</font>:
- 再次执行这个配置,后果如下图红框所示,只有这三个办法被执行:first1Test、first3Test、second3Test,可见标签表达式失效了:
- 在maven命令和surefire插件中应用标签表达式的操作就不在文中执行了,请您自行验证;
自定义注解
- JUnit反对自定义注解,先回顾之前的代码,看咱们是如何给办法打标签的,以first3Test办法为例:
@Test @Tag("hard") @DisplayName("first-3") void first3Test() { log.info("first3Test"); assertEquals(2, Math.addExact(1, 1)); }
- 接下来咱们创立一个注解,将<font color="blue">@Tag("hard")</font>替换掉,新注解的源码如下,可见仅是一个一般的注解定义:
package com.bolingcavalry.tag.service.impl;import org.junit.jupiter.api.Tag;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target({ ElementType.TYPE, ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)@Tag("hard")public @interface Hard {}
- 批改first3Test办法的注解,去掉<font color="blue">@Tag("hard")</font>,改为<font color="red">@Hard</font>:
@Test @Hard @DisplayName("first-3") void first3Test() { log.info("first3Test"); assertEquals(2, Math.addExact(1, 1)); }
- 执行后面创立的<font color="blue">tag-important</font>配置,可见hard标签的过滤仍旧无效:
更加简化的自定义注解
- 上述Hard注解取代了<font color="blue">@Tag("hard")</font>,其实还能够更进一步对已有注解做简化,上面是个新的注解:HardTest.java,和Hard.java相比,多了个<font color="blue">@Test</font>,作用是集成了Test注解的能力
package com.bolingcavalry.tag.service.impl;import org.junit.jupiter.api.Tag;import org.junit.jupiter.api.Test;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target({ ElementType.TYPE, ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)@Tag("hard")@Testpublic @interface HardTest {}
- 于是,<font color="blue">first3Test</font>办法的注解能够改成上面的成果,可见Test和Tag注解都去掉了:
@HardTest @DisplayName("first-3") void first3Test() { log.info("first3Test"); assertEquals(2, Math.addExact(1, 1)); }
- 执行后面创立的<font color="blue">tag-important</font>配置,可见hard标签的过滤仍旧无效:
标签命名标准
最初一起来看看给标签取名时有哪些要留神的中央:
- 标签名左右两侧的空格是有效的,执行测试的时候会做trim解决,例如上面这个标签会被当作<font color="blue">hard</font>来过滤:
- 标签名不能有这六个符号<font color="blue">, ( ) & | !</font>
- 至此,JUnit5的标签过滤和自定义注解性能都学习实现了,有了这些能力,咱们能够更加灵便和得心应手的应酬不同的场景和需要;
你不孤独,欣宸原创一路相伴
- Java系列
- Spring系列
- Docker系列
- kubernetes系列
- 数据库+中间件系列
- DevOps系列
欢送关注公众号:程序员欣宸
微信搜寻「程序员欣宸」,我是欣宸,期待与您一起畅游Java世界...
https://github.com/zq2599/blog_demos