Junit特点
JUnit 是一个开放的资源框架,⽤用于编写和运⾏测试。
提供注解来识别测试⽅方法。
提供断⾔言来测试预期结果。
JUnit 测试允许你编写代码更快,并能提高质量。
JUnit 优雅简洁。没那么复杂,花费时间较少。
JUnit测试可以自动运⾏并且检查⾃自身结果并提供即时反馈。所以也没有必要人工梳理测试结果的报告。
JUnit测试可以被组织为测试套件,包含测试⽤用例例,甚⾄至其他的测试套件。
JUnit在一个条中显示进度。如果运⾏行行良好则是绿⾊色;如果运⾏行行失败,则变成红⾊
Junit注解
Junit执行过程
套件测试
运行器RunWith
测试方法:用@Test注解的一些函数
测试类:包含一个或多个测试方法的一个ATest.java文件
测试集:是一个suite,可能包含多个测试类
测试运行器:决定了用什么方式偏好去运行这些测试集/类/方法。
常见运行器
@RunWith(Parameterized)参数化运行器,配合@Parameters使用Junit的参数化功能
@RunWith(Suite.class) @SuiteClasses(ATest.class,BTest.class,CTest.class)测试集运行器配合使用测试集功能
@RunWith(Junit4.class),Junit4的默认运行器
@RunWith(Junit38ClassRunner.class),用于兼容Junit3.8的运行器
一些其他运行器具备更多功能,例如@RunWith(SpringJunit4ClassRunner.class集成了Spring的一些功能
以suite为例:一些依赖关系的类可以用套件方法执行。
注意:此处配置的顺序是执行的顺序。
@RunWith(Suite.class)
@Suite.SuiteClasses({
TestcaseSuite.case1.TestRun1.class
TestcaseSuite.case1.TestRun2.class
})
Junit4
Junit4注解
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
Junit4注解
@Test
@BeforeClass 必须用static修饰符,每个测试类执行之前需要执行
@AfterClass 必须用static修饰符,每个测试类执行之后需要执行
@Before 每个case执行前需要执行
@After 每个case执行后需要执行
@Ignore 忽略,不执行该case,写在@Test下,忽略某个case;写在class上,忽略整个类。
执行一个指定的类:mvn -Dtest=类名【此处的类名需要 copy reference】
如果报错导入
<build>
<defaultGoal>compile</defaultGoal>
</build>
执行test下的case:mvn clean test 报错,待解决

Junit5
Junit5框架构成:JUnit Platform+JUnit Jupiter+JUnit Vintage
JUnit Platform:Junit向测试平台演进,提供平台功能的模块,通过JUnit Platform,其他的自动化测试引擎或开发人员自己定制的引擎都可以介入Junit实现对接和执行。比如:将TestNG运行在Junit上
JUnit Jupiter:是Junit5 的核心,承载Junit4原有功能的演进。包含了很多丰富的新特性来使Junit自动化测试更加方便、功能更加丰富和强大。JUnit Jupiter本身是基于JUnit Jupiter的引擎实现。
JUnit Vintage:对Junit3、Junit4版本兼容的测试引擎,是旧版本Junit自动化测试脚本也可以运行在Junit5下。
Junit5新特性
嵌套单元测试、Lambda支持、参数化测试、重复测试、动态测试
Junit5注解:
@Test
@BeforeAll:举例在所有的testcase执行前需要进行登录获取cookie操作。需要用static修饰
@AfterAll:举例在所有testcase执行结束需要调用driver.quit方法。需要用static修饰
@BeforeEach:每个case前执行
@AfterEach:每个case后执行
@RepeatedTest(#)重复执行#遍,放在@Test后面
@DisplayName("")展示名称:写在类名前,显示类名;写在@test后,显示每个case的名称
@Nested 先执行主类,再将后面的类倒序执行
@Disabled 跳过但提示执行完成
@Timeout 超时测试
@ExtendWith 为测试类或测试方法提供扩展类引用
套件测试:
@RunWith(JUnitPlatform.class)
@SelectPackage({“com.packsgeA”,“com.packsgeB”})
@IncludePackages(“包名”)
@SelectClasses({xx.class,xxx.class,xxxx.class})
@IncludeTags(“production”):@Tags写在@Test下,作为筛选条件存在
@ExcludeTags(“PROD”)
@RunWith(JUnitPlatform.class)
@SelectPackages({"TestcaseSuite"})
@IncludePackages({
"TestcaseSuite.case1.TestRun1",
"TestcaseSuite.case2.TestRun2"
})
@RunWith(Suite.class)
@Suite.SuiteClasses({
TestcaseSuite.case1.TestRun1.class
})

参数化测试
@ValueSource: 为参数化测试指定入参来源,支持八大基础类以及String类型,Class类型
@NullSource: 表示为参数化测试提供一个null的入参
@EnumSource: 表示为参数化测试提供一个枚举入参
@CsvFileSource:表示读取指定CSV文件内容作为参数化测试入参
@MethodSource:表示读取指定方法的返回值作为参数化测试入参(注意方法返回需要是一个流)
@ParameterizedTest
@ValueSource(strings = {"one", "two", "three"})
@DisplayName("参数化测试1")
public void parameterizedTest1(String string) {
System.out.println(string);
Assertions.assertTrue(StringUtils.isNotBlank(string));
}
@ParameterizedTest
@CsvFileSource(resources = "/test.csv") //指定csv文件位置
@DisplayName("参数化测试-csv文件")
public void parameterizedTest2(String name, Integer age) {
System.out.println("name:" + name + ",age:" + age);
Assertions.assertNotNull(name);
Assertions.assertNotNull(age);
}
@ParameterizedTest
@MethodSource("method") //指定方法名
@DisplayName("方法来源参数")
public void testWithExplicitLocalMethodSource(String name) {
System.out.println(name);
Assertions.assertNotNull(name);
}
static Stream<String> method() {
return Stream.of("apple", "banana");
}
异常测试
@Test
@DisplayName("异常测试")
public void exceptionTest() {
ArithmeticException exception = Assertions.assertThrows(
//扔出断言异常
ArithmeticException.class, () -> System.out.println(1 % 0));
}
超时测试
@Test
@DisplayName("超时测试")
public void timeoutTest() {
//如果测试方法时间超过1s将会异常
Assertions.assertTimeout(Duration.ofMillis(1000), () -> Thread.sleep(500));
}
嵌套单元测试
JUnit5提供了嵌套单元测试用于更好表示各个单元测试类之间的关系。平时我们写单元测试时一般都是一个类对应一个单元测试类。不过有些互相之间有业务关系的类,他们的单元测试完全是可以写在一起,使用内嵌的方式表示,减少测试类的数量防止类爆炸。
JUnit 5提供了@Nested 注解,能够以静态内部成员类的形式对测试用例类进行逻辑分组
public class NestedTestDemo {
@Test
@DisplayName("Nested")
void isInstantiatedWithNew() {
System.out.println("最一层--内嵌单元测试");
}
@Nested
@DisplayName("Nested2")
class Nested2 {
@BeforeEach
void Nested2_init() {
System.out.println("Nested2_init");
}
@Test
void Nested2_test() {
System.out.println("第二层-内嵌单元测试");
}
@Nested
@DisplayName("Nested3")
class Nested3 {
@BeforeEach
void Nested3_init() {
System.out.println("Nested3_init");
}
@Test
void Nested3_test() {
System.out.println("第三层-内嵌单元测试");
}
}
}
}
重复测试
@RepeatedTest(10) //表示重复执行10次
@DisplayName("重复测试")
public void testRepeated() {
Assertions.assertTrue(1 == 1);
}