设置标签
    
    在父工程junitpractice里新建名为tag的子工程,今天的单元测试代码都写在这个tag工程中;
    
    一共写两个测试类,第一个FirstTest.java如下,可见类上有Tag注解,值为first,另外每个方法上都有Tag注解,其中first1Test方法有两个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中做标签过滤
    
    如下图所示,点击红框中的Edit Configurations…:
    
    在这里插入图片描述
    
    2. 如下图红框,在弹出的窗口上新增一个JUnit配置:
   
    在这里插入图片描述
    
    3. 接下来的操作如下图所示,Test kind选择Tags,就会按照标签过滤测试方法,Tag expression里面填写过滤规则,后面会详细讲解这个规则,这里先填个已存在的标签important:
   
    在这里插入图片描述
    
    4. 创建好JUnit配置后,执行下图红框中的操作即可执行单元测试:
   
在这里插入图片描述
    执行结果如下,所有打了important标签的测试方法被执行:
    
    在这里插入图片描述
   
    用maven命令时做标签过滤
    
    前面试过IDEA上按标签过滤测试方法,其实用maven命令执行单元测试的时候也能按标签来过滤,接下来试试;
    
    在父工程junitpractice的pom.xml所在目录下,执行以下命令,即可开始单元测试,并且只执行带有标签的方法:
    
    mvn clean test -Dgroups=“important”
    
    执行完毕后结果如下:
    
    在这里插入图片描述
    
    4. 翻看日志,可见只有打了important标签的测试方法被执行了,如下图红框所示:
   
在这里插入图片描述
    再看看其他子工程的执行情况,用前一篇文章里的conditional为例,可见没有任何测试方法被执行,如下图红框所示:
    
    在这里插入图片描述
   
    再去看看surefire插件给出的测试报告,报告文件在junitpractice\tag\target\surefire-reports目录下,下图红框中的文件就是测试报告:
    
    在这里插入图片描述
   
打开上图红框中的一个文件,如下图红框,可见只有打了important标签的测试方法被执行了:
在这里插入图片描述
    以上就是maven命令执行单元测试时使用标签过滤的方法,接下来试试在使用maven-surefire-plugin插件时如何通过做标签过滤
    
    用surefire插件时做标签过滤
    
    surefire是个测试引擎(TestEngine),以maven插件的方式来使用,打开tag子工程的pom.xml文件,将build节点配置成以下形式,可见groups就是标签过滤节点,另外excludedGroups节点制定的hard标签的测试方法不会执行:
    org.springframework.boot
    
    spring-boot-maven-plugin
    maven-surefire-plugin
    
    2.22.2
important
hard
    在tag子工程的pom.xml所在目录,执行命令mvn clean test即可开始单元测试,结果如下,可见打了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配置,从之前的important改为important | hard:
    
    在这里插入图片描述
    
    5. 再次执行这个配置,结果如下图红框所示,只有这三个方法被执行:first1Test、first3Test、second3Test,可见标签表达式生效了:
   
    在这里插入图片描述
    
    6. 在maven命令和surefire插件中使用标签表达式的操作就不在文中执行了,请您自行验证;
   
    自定义注解
    
    JUnit支持自定义注解,先回顾之前的代码,看咱们是如何给方法打标签的,以first3Test方法为例:
    
    @Test
    
    @Tag(“hard”)
    
    @DisplayName(“first-3”)
    
    void first3Test() {
    
    
    log.info(“first3Test”);
    
    assertEquals(2, Math.addExact(1, 1));
    
    }
    
    接下来咱们创建一个注解,将@Tag(“hard”)替换掉,新注解的源码如下,可见仅是一个普通的注解定义:
    
    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方法的注解,去掉@Tag(“hard”),改为@Hard:
    
    @Test
    
    @Hard
    
    @DisplayName(“first-3”)
    
    void first3Test() {
    
    
    log.info(“first3Test”);
    
    assertEquals(2, Math.addExact(1, 1));
    
    }
    
    执行前面创建的tag-important配置,可见hard标签的过滤依旧有效:
    
    在这里插入图片描述
   
    更加简化的自定义注解
    
    上述Hard注解取代了@Tag(“hard”),其实还可以更进一步对已有注解做简化,下面是个新的注解:HardTest.java,和Hard.java相比,多了个@Test,作用是集成了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”)
    
    @Test
    
    public @interface HardTest {
    
    
    }
    
    于是,first3Test方法的注解可以改成下面的效果,可见Test和Tag注解都去掉了:
    
    @HardTest
    
    @DisplayName(“first-3”)
    
    void first3Test() {
    
    
    log.info(“first3Test”);
    
    assertEquals(2, Math.addExact(1, 1));
    
    }
    
    亚马逊测评 www.yisuping.cn
   
 
