8,超时处理
- 使用 JUnit5 自带的超时处理,当测试用例执行时间超过设置的执行时间,那么用例结果为执行失败。
package MethodSourceDemo;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import java.util.concurrent.TimeUnit;
import static java.lang.Thread.sleep;
public class TimeoutTest {
@Test
@Timeout(5) //设置用例的超时时间为5秒
void timeoutDemo() throws InterruptedException {
sleep(6000); //设置用例休眠6秒后执行
System.out.println("超时用例");
}
@Test //没有设置超时时间的用例不受影响
void timeoutDemo2(){
System.out.println("超时用例2");
}
@Test
//通过value参数配置数量,通过unit参数配置时间单位
@Timeout(value = 10, unit = TimeUnit.MILLISECONDS)
void setUp() throws InterruptedException {
sleep(6000);
System.out.println("超时用例33");
}
}
9,用例显示名称
(1)@DisplayName注解定义用例名称
package MethodSourceDemo;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
public class DisplaynameTest {
// 通过DisplayName注解定义
@DisplayName("第一条用例")
@Test
void FirstCase(){
System.out.println("第一条用例");
}
@DisplayName("第二条用例")
@Test
void SecondCase(){
System.out.println("第二条用例");
}
}
(2) 通过注解 @DisplayNameGenerator
实现生成器
- 在测试类前加上配置 @DisplayNameGeneration(DisplayNameGenerator.Standard.class)
package MethodSourceDemo;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.DisplayNameGenerator;
import org.junit.jupiter.api.Test;
// 默认配置,不会有变化
@DisplayNameGeneration(DisplayNameGenerator.Standard.class)
public class DisplaynameTest {
@Test
void First_Case() {
System.out.println("第一条用例");
}
@Test
void Second_Case() {
System.out.println("第二条用例");
}
}
(3)通过配置文件配置
- 在路径
src/test/resources
中添加junit-platform.properties配置文件。 - 在配置文件中添加对应的配置属性。
# 全局配置Display name 为连接类名与方法名
junit.jupiter.displayname.generator.default = \
org.junit.jupiter.api.DisplayNameGenerator$IndicativeSentences
(4)配置优先级
10,嵌套测试
- 定制化执行用例
- 用例层级、业务关系更加清晰
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
public class NestedDemo {
@Nested
class AuthorityManagment{
@Nested
class Management{
@Test
void managementLogin(){
System.out.println("管理员登录测试");
}
@Nested
class ManagementDelete{
@Test
void deleteUser(){
System.out.println("删除用户");
}
}
}
@Nested
class Client{
}
}
@Nested
class DataManagement{
@Nested
class CreditScore{
@Nested
class MortgageScore{
@Test
void getMortgageScore(){
System.out.println("房屋贷款");
}
}
}
}
}
11,执行顺序@Order
使用场景:
- 测试用例有业务逻辑相关
- 集成测试(主流程测试)
排序方式:
- 方法排序
- 类排序
- Suite
- 官方网站没有明确说明默认排序的具体规则
方法排序:
package orderDemo;
import org.junit.jupiter.api.*;
//设定排序方法为注解指定排序,与@Order结合一起使用
//@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
//设定排序方法为,根据DisplayName进行排序,与@DisplayName结合一起使用
//@TestMethodOrder(MethodOrderer.DisplayName.class)
//设计排序类型为随机排序
//@TestMethodOrder(MethodOrderer.Random.class)
// 设置排序类型为按方法名排序
@TestMethodOrder(MethodOrderer.MethodName.class)
public class OrderdemoTest {
@Test
// @Order(2)
// @DisplayName("a用例")
void firstTest() {
System.out.println("第1条用例");
}
@Test
// @Order(3)
// @DisplayName("c用例")
void TwoTest() {
System.out.println("第2条用例");
}
@Test
// @Order(1)
// @DisplayName("b用例")
void ThreeTest() {
System.out.println("第3条用例");
}
}
类排序:
package orderDemo;
import org.junit.jupiter.api.*;
//设定排序方法为注解指定排序,与@Order结合一起使用
//@TestClassOrder(ClassOrderer.OrderAnnotation.class)
//设定排序方法为,根据DisplayName进行排序,与@DisplayName结合一起使用
//@TestClassOrder(ClassOrderer.DisplayName.class)
//设定排序类型为随机排序
//@TestClassOrder(ClassOrderer.Random.class)
// 设置排序类型为按类名排序
//@TestClassOrder(ClassOrderer.ClassName.class)
public class ClassOrderTest {
// 因为是多类执行,所以需要结合@Nested注解
@Nested
@Order(1)
// @DisplayName("b")
class PrimaryTests {
@Test
void test1() {
System.out.println("第一条用例");
}
}
@Nested
@Order(2)
// @DisplayName("a")
class SecondaryTests {
@Test
void test2() {
System.out.println("第二条用例");
}
}
}
使用默认配置指定顺序
- 新建配置文件(路径:
src/main/resources/junit-platform.properties
) - 在配置文件中写入对应的配置信息
- 可以分别指定方法的默认配置和类的默认配置
#默认排序方式为随机排序
junit.jupiter.testmethod.order.default = org.junit.jupiter.api.MethodOrderer$Random
#默认排序方式为通过方法名排序
junit.jupiter.testmethod.order.default = org.junit.jupiter.api.MethodOrderer$MethodName
#默认排序方式为通过Order注解指定
junit.jupiter.testmethod.order.default = org.junit.jupiter.api.MethodOrderer$OrderAnnotation
#默认排序方式为通过DisplayName排序
junit.jupiter.testmethod.order.default = org.junit.jupiter.api.MethodOrderer$DisplayName
#默认排序方式为随机排序
junit.jupiter.testclass.order.default = org.junit.jupiter.api.ClassOrderer$Random
#默认排序方式为通过类名排序
junit.jupiter.testclass.order.default = org.junit.jupiter.api.ClassOrderer$ClassName
#默认排序方式为通过DisplayName排序
junit.jupiter.testclass.order.default = org.junit.jupiter.api.ClassOrderer$DisplayName
#默认排序方式为通过Order注解指定
junit.jupiter.testclass.order.default = org.junit.jupiter.api.ClassOrderer$OrderAnnotation
12,重复性测试 @RepeatedTest
使用场景:
- 需要用例执行多次的场景
- 接口的幂等性测试
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
public class RepeatTest {
// @Test //如果添加 @Test 注解,则会多执行一次,使用重复测试注解的话,没必要用@Test
@RepeatedTest(2) // 注解内需要传递控制重复次数的参数
void hogwarts(){
System.out.println("霍格沃兹测试开发支付成功");
}
// value 表示要重复几次
// displayName 对应执行用例的displayname,没有添加@DisplayName注解时,会默认调用对应的测试方法
// currentRepetition 第几次重复
// totalRepetitions 代表总共要重复的次数
@RepeatedTest(value = 3, name = "{displayName} {currentRepetition} of {totalRepetitions}")
@DisplayName("test001")
void firstTest(){
System.out.println("该用例为重复测试用例");
}
}
13,标记测试用例@Tag
使用场景:
- 通过 Tag 对用例分组:
- 环境分组: 测试环境、预发布环境
- 阶段分组: 冒烟用例
- 版本分组: V1.1、V1.2
标记用例方法:
- 设置标签
- 根据标签执行
- 结合 Maven 执行
- 结合测试套件执行
自定义标签:
package tagDemo;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
//定义标签
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Tag("hogwarts")
@Test
@interface PreprodTest {
}
设置标签:
package tagDemo;
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;
public class TagDemoTest {
@Tag("grey")
@Test
void hogwarts(){
System.out.println("灰度环境");
}
@Tag("test")
@Test
void hogwarts2(){
System.out.println("测试环境");
}
@Tag("dev")
@Test
void hogwarts3(){
System.out.println("开发环境");
}
@Tag("dev")
@Tag("test")
@Test
void hogwarts4(){
System.out.println("开发+测试环境");
}
//使用自定义标签,PreprodTest为定义的接口名称
//使用mvn test -Dgroups="hogwarts" 执行该用例时,标签名应该使用接口定义的@Tag("hogwarts")这个标签名
@PreprodTest
void testCustomTag(){
System.out.println("自定义的标签");
}
}
Maven 结合 tag 构建-修改 pom 文件
需要导入的依赖配置:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<!-- 要执行的标签 -->
<groups>test</groups>
<!-- 不要执行的标签 -->
<excludedGroups>dev</excludedGroups>
</configuration>
</plugin>
</plugins>
</build>
-
groups
表示执行包含标签或者标签表达式的用例。 -
excludedGroups
表示不执行包含该标签或者标签表达式的用例。 - 使用命令
mvn clean test
执行用例。
Maven 结合 tag 构建-使用命令行构建
- 如果使用命令行的同时也配置了 pom 文件, pom 的配置优先级更高
# 执行 test 标签的用例
mvn clean test -Dgroups="test"
# 执行不含test 标签的用例
mvn clean test -DexcludedGroups="test"
命名规范
Tag表达式
表达式在pom文件使用:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- & 在xml 中表示 & 与的关系 -->
<groups>test&dev</groups>
<!-- 不要执行的标签 -->
<!-- <excludedGroups>主流程方法</excludedGroups>-->
</configuration>
<version>2.22.2</version>
</plugin>
表达式在命令行使用:
# 执行 没有test 标签的用例
mvn clean test -Dgroups="!test"
# 执行 dev 或 test 标签的用例
mvn clean test -Dgroups="dev|test"
# 执行既有 dev 也有 test 标签的用例
mvn clean test -Dgroups="dev&test"
14,禁用测试用例@Disable
- 给用例添加禁用标识。
- 被禁用的用例执行后会添加跳过的状态。
- 可以禁用测试类、也可以禁用测试方法
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
//在类名添加Disabled注解
//注意:IDEA 不支持,maven 构建才支持跳过Disabled注解的测试类
//@Disabled
//@Disabled("Disabled until bug #99 has been resolved") //也可以在注解里加上跳过该用例的原因说明
public class DisableDemoTest {
@Test
void test001() {
System.out.println("测试用例1");
}
@Test
void test002() {
System.out.println("测试用例2");
}
//在方法名添加Disabled注解
//IDEA和 maven 构建都支持跳过Disabled注解的测试方法
@Disabled("Disabled until bug #42 has been resolved")
@Test
void testWillBeExecuted() {
System.out.println("跳过的测试用例");
}
}