Java测试框架-junit5
java当前主流的测试框架有两个:TESTNG、Junit5;这两个框架在功能上都比较完善,也没有说哪个更好,因为笔者平时用的比较多的是Junit5,所以本文主要讲的是Junit5的使用
1、Junit5的构成
Junit5的框架主要有三个部分组成分别是:JUnit Platform + JUnit Jupiter + JUnit Vintage3
-
JUnit Platform :
其主要作用是在 JVM 上启动测试框架。它定义了一个抽象的 TestEngine API 来定义运行在平台上的测试框架;也就是说其他的自动化测试引擎或开发人员⾃⼰定制的引擎都可以接入 Junit 实现对接和执行。同时还支持通过命令行、Gradle 和 Maven 来运行平台(这对于我们做自动化测试至关重要) -
JUnit Jupiter:
这是 Junit5 的核心,可以看作是承载 Junit4 原有功能的演进,包含了 JUnit 5 最新的编程模型和扩展机制;很多丰富的新特性使 JUnit ⾃动化测试更加方便、功能更加丰富和强大。也是测试需要重点学习的地方;Jupiter 本身也是⼀一个基于 Junit Platform 的引擎实现,对 JUnit 5 而言,JUnit Jupiter API 只是另一个 API!。 -
JUnit Vintage3
Junit 发展了10数年,Junit 3 和 Junit 4 都积累了大量的⽤用户,作为新一代框 架,这个模块是对 JUnit3,JUnit4 版本兼容的测试引擎,使旧版本 junit 的⾃动化测试脚本也可以顺畅运行在 Junit5 下,它也可以看作是基于 Junit Platform 实现的引擎范例。
junit5依赖:
<!--junit5-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.8.2</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-runner</artifactId>
<version>1.8.2</version>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-launcher</artifactId>
<version>1.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-console-standalone</artifactId>
<version>1.8.2</version>
<scope>test</scope>
</dependency>
2、Junit5的常用注解
注解的使用实例
// @BeforeAll : 在测试类执行之前执行的方法 必须用static 相当与testng中的@BeforeClass
@BeforeAll
public static void beforeAll(){
System.out.println("beforeAll");
}
// @BeforeEach : 在每个测试用例前执行的方法 相当于testng的@BeforeMethod
@BeforeEach
public void beforeEach(){
System.out.println("beforeEach");
}
// @Disabled 相当但junit4的Ignore 跳过该测试用例
@Test
@Disabled
void test01(){
System.out.println("test01");
}
// @RepeatedTest 重复执行
@RepeatedTest(4)
@Tag("tagDemo")
void test02(){ System.out.println("test02");
}
// @DisplayName("name") 展示用例名
@Test
@Tag("tagDemo2")
@DisplayName("测试用例3")
void test03(){
System.out.println("test03");
}
// @AfterEach : 在测试类执行之后执行的方法
@AfterEach
public void afterEach(){
System.out.println("afterEach");
}
// @AfterAll : 在每个测试用例后执行的方法 必须用static声明
@AfterAll
public static void afterAll(){
System.out.println("afterAll");
}
// @Order定义执行顺序
// 需要先在类上打上@TestMethodOrder(MethodOrderer.OrderAnnotation.class)注解
@Test
@Order(1)
public void divideTest(){
int divideResult = Calculator.divide(8, 2);
assertEquals(4,divideResult);
}
3、测试套件的常用注解
有些测试用例可能每次都要执行,但是可能有些只有特定版本才需要运行,这个时候测试套件就可以帮助我们很好地将测试用例管理起来,指定需要运行的测试套件。
套件注解实例:
// 1 @RunWith+@SelectPackages+@IncludePackages+@ExcludePackages
// @SelectPackages 选择需要执行的测试包
// @IncludePackages 只执行选中的测试包 需要与@SelectPackages配合使用
// @ExcludePackages过滤掉所选择的测试包
@RunWith(JUnitPlatform.class)
@SelectPackages({ "com.junit5.test2", "com.junit5.test"})
@IncludePackages({ "com.junit5.test2"})
@ExcludePackages({ "com.junit5.test2"})
public class SuiteTest {}
// 2 @RunWith+@SelectClasses
// @SelectClasses选中需要执行的测试类
@RunWith(JUnitPlatform.class)
@SelectClasses({ LoginTest.class, Junit5Test.class})
public class SuiteTest02 {}
// 3 @RunWith+@SelectPackages+@IncludeClassNamePatterns+@ExcludeClassNamePatterns
// @SelectPackages 选中需要执行的测试包
// @IncludeClassNamePatterns 只执行测试包中对应的测试类 与@SelectPackages配合使用
// @ExcludeClassNamePatterns 过滤掉测试包中的测试类
@RunWith(JUnitPlatform.class)
@SelectPackages({ "com.junit5.test2", "com.junit5.test"})
@IncludeClassNamePatterns({ "com.junit5.test.Junit5Test", "com.junit5.test2.LoginTest"})
@ExcludeClassNamePatterns({ "com.junit5.test.Junit5Test"})
public class SuiteTest03 {}
// 4 @RunWith+@SelectPackages+@IncludeTags+@ExcludeTags
// @SelectPackages选中需要执行的测试包
// @IncludeTags 执行包含标签的用例 ,标签打在测试用例前
// @ExcludeTags 过滤掉包含标签的用例
@RunWith(JUnitPlatform.class)
@SelectPackages({ "com.junit5.test2", "com.junit5.test"})
@IncludeTags({ "tagDemo"})
@ExcludeTags({ "tagDemo2"})
public class SuiteTest04 {}
4、Junit5 的断言方式:
- 上面试Junit5自带的断言方式,如果需要更复杂的断言可以使用hamcrest断言方式;
- 软断言:如果一个用例需要进行多次断言,就需要用到assertAll(需要先设置java8语法),使用软断言后不会因为一个断言的失败报错而中断测试
- 软断言实例:
@Test
void addTest(){
assertAll(
()->assertEquals(9==9),
()->assertEquals(7==2),
()->assertEquals(10==10)
);
}
// 二:现将assert可执行语句进行储存,再用assertAll进行断言
ArrayList<Executable> assertList = new ArrayList<>();
for(int i = 0;i<3;i++){
int result = 1 + i;
assertList.add({
// 先将断言语句存起来
() -> assertEquals(3,result);
})
}
assertAll(assertList.Stream());
5、Junit5并发测试
junit5 从5.3开始支持多线程并发测试,
需要在配置文件junit-platform.properties配置相关信息
配合@RepeatedTest注解使用
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=2
6、参数化方式
注解 | 说明 |
---|---|
@valueSource | 通过注解可以直接指定携带的运行参数 |
@EnumSource | 枚举参数元,允许我们通过将参数值有给定的Enum枚举类型传入 |
@MethodSource | 通过其他的Java方法函数来作为参数源 |
@ArgumentSource | 参数类参数源,应用类必须实现ArgumentsProvide接口 |
@CSVSource | csv格式作为参数源 |
@CSVFileSource | csv文件作为参数源 |
以上是Junit5的参数化方式,在这里我就不一一介绍了,本人用的更多的MethodSource+yaml的参数化方式;因为yaml文档能够比较清晰地定义各种类型的参数,结合MethodSource注解就能够很方便的构建出不同类型的参数
简单的MethodSource实例:
// 添加成员@ParameterizedTest
@MethodSource("testData")
public void successTest(String name,String phone) {
System.out.println("name: " + name +"phone: " + phone)
}
// 返回用例数据
public static Stream<Arguments> testData() {
return Stream.of(
Arguments.arguments("周杰伦","12121221211"),
Arguments.arguments("林俊杰","12121221212"),
Arguments.arguments("王力宏","12121221213"));
}
以上就是笔者本次分享的内容