2023.8.27 关于 Junit5 详解

目录

引言

注解 

断言

用例的执行顺序 

参数化

测试套件 


引言

  • Junit 是一个基于Java语言的单元测试框架
  • Selenium 是一个用于Web应用程序测试的自动化测试框架
  • 结合二者能让我们的 Web自动化测试 更加完善和全面

注意:

本文所讲的内容,均基于以下依赖,我们需自己手动引入至 pom.xml 中

<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java -->
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.141.59</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.11.0</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.9.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-params -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.9.2</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite -->
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-suite</artifactId>
            <version>1.9.1</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-engine -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.9.2</version>
            <scope>test</scope>
        </dependency>

注解 

@Test

public class JunitTest {

    @Test
    void Test01() {
        System.out.println("这是 JuniteTest 里面的 Test01");
    }
}
  • 将 @Test 注解放置在一个无参方法上,表示该方法是一个测试方法
  • 执行 JunitTest 类时,会自动执行该类中所有带有 @Test 注解的测试方法

@BeforeEach

public class JunitTest {

    @BeforeEach
    void SetUp() {
        System.out.println("这是我们BeforeEach里面的语句");
    }

    @Test
    void Test01() {
        System.out.println("这是 JuniteTest 里面的 Test01");
    }

    @Test
    void Test02() {
        System.out.println("这是 JuniteTest 里面的 Test02");
    }
}

该段代码执行结果:

  • @BeforeEach注解被用于标记一个方法,该方法会在每个测试方法执行之前被自动调用

@BeforeAll

public class JunitTest {

    @BeforeAll
    static void SetUp() {
        System.out.println("这是我们BeforeAll里面的语句");
    }

    @Test
    void Test01() {
        System.out.println("这是 JuniteTest 里面的 Test01");
    }

    @Test
    void Test02() {
        System.out.println("这是 JuniteTest 里面的 Test02");
    }
}

该段代码执行结果如下:

  • @BeforeAll 注解被用于标记一个方法,该方法会在所有测试方法执行之前被自动调用
  • @BeforeAll 注解修饰的方法必须是静态方法

@AfterEach

public class JunitTest {

    @AfterEach
    void TearDown() {
        System.out.println("这是AfterEach的语句");
    }

    @Test
    void Test01() {
        System.out.println("这是 JuniteTest 里面的 Test01");
    }
    
    @Test
    void Test02() {
        System.out.println("这是 JuniteTest 里面的 Test02");
    }
}

该段代码执行结果:

  • @AfterEach注解被用于标记一个方法,该方法会在每个测试方法执行之后被自动调用

@AfterAll

public class JunitTest {

    @AfterAll
    static void TearDown() {
        System.out.println("这是AfterAll的语句");
    }

    @Test
    void Test01() {
        System.out.println("这是 JuniteTest 里面的 Test01");
    }

    @Test
    void Test02() {
        System.out.println("这是 JuniteTest 里面的 Test02");
    }

该段代码执行结果:

  • @AfterAll 注解被用于标记一个方法,该方法会在所有测试方法执行之后被自动调用
  • @AfterAll 注解修饰的方法必须是静态方法

断言

断言是否匹配

public class JunitTest {

    @Test
    void Test09(){
        int n = 1;
//        断言是否相互匹配
        Assertions.assertEquals(2,num);
//        断言是否相互不匹配
        Assertions.assertNotEquals(2,num);
    }
}

该段代码运行结果:

  • assertEquals() 方法的第一个参数为 期望结果,第二个参数为 实际结果
  • 当 assertEquals() 方法的期望结果和实际结果不一致时,便会打印上图报错日志
  • 当 assertEquals() 方法的期望结果和实际结果一致时,便什么都不会发生,继续执行其后面的代码
  • 不难理解 assertNotEquals() 方法 跟 assertEquals() 方法 的逻辑正好相反

断言是否为真

public class JunitTest {

    @Test
    void Test09(){
        boolean b = false;
//        断言是否为真
        Assertions.assertTrue(b);
//        断言是否为假
        Assertions.assertFalse(b);
    }
}

该段代码运行结果:

  • assertTrue() 方法用来判断所给状态是否为真
  • 当 assertTrue() 方法中的状态不为真,便会打印上图报错日志
  • 当 assertTrue() 方法中的状态为真,便什么都不会发生,继续执行其后面的代码
  • 不难理解 assertFalse() 方法 跟 assertTrue() 方法 的逻辑正好相反

断言是否为空

public class JunitTest {

    @Test
    void Test09(){
//        断言是否为空
        String str = null;
        String str2 = "1";
        Assertions.assertNull(str2); //当传入 str 时 该断言不会报错
//        断言是否不为空
        Assertions.assertNotNull(str2);
    }
}

该段代码运行结果:

  • assertNull() 方法用来判断所给参数是否为 null
  • 当 assertNull() 方法中的参数不为 null,便会打印上图报错日志
  • 当 assertNull() 方法中的参数为 null,便什么都不会发生,继续执行其后面的代码
  • 不难理解 assertNotNull() 方法 跟 assertNull() 方法 的逻辑正好相反

用例的执行顺序 

一个类中默认的用例执行顺序是什么?

  • 在 Junit 框架中,默认的测试用例执行顺序是不确定的,也就是并不会按照我们所编写的用例的顺序来执行!

测试用例自定义顺序

//随机执行测试方法
//@TestMethodOrder(MethodOrderer.Random.class)
//按自定义顺序执行测试方法
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class JunitTest {

    @Order(1)
    @Test
    void A() {
        System.out.println("这是 Junite 里面的 A 测试用例");
    }

    @Order(3)
    @Test
    void B() {
        System.out.println("这是 Junite 里面的 B 测试用例");
    }
    
    @Order(2)
    @Test
    void Test01() {
        System.out.println("这是 JuniteTest 里面的 Test01");
    }

    @Order(4)
    @Test
    void Test02() {
        System.out.println("这是 JuniteTest 里面的 Test02");
    }
}

该段代码执行结果:

  •   @TestMethodOrder(MethodOrderer.OrderAnnotation.class) 注解 写在相应类的上方
  • 使用 @Order 注解并写在相应测试方法的上方,填写参数进行执行顺序的排序
  • @TestMethodOrder(MethodOrderer.Random.class) 注解 表示该类随机执行测试方法,不需要搭配 @Order 注解,且每次执行该类时,测试方法的执行顺序都不相同

参数化

  • 在写含有参数的测试方法时, @ParameterizedTest 注解 是必不可少的,它必须写在含参测试方法的上面,进行相应申明
  • 使用 @ParameterizedTest 注解 时,无需再加 @Test 注解

单参数

  • 单参数指的是测试方法有且仅有一个参数
public class JunitTest {

    @ParameterizedTest
    @ValueSource(ints = {1,2,3})
    void Test04(int num){
        System.out.println(num);
    }

    @ParameterizedTest
    @ValueSource(strings = {"小","林"})
    void Test05(String str) {
        System.out.println(str);
    }
}

该段代码执行结果:

  • 该段代码 通过 @ValueSource 注释 来提供数据的来源

public class JunitTest {

    @ParameterizedTest
    @CsvFileSource(resources = "test01.csv")
    void Test06(String name) {
        System.out.println(name);
    }
}

该段代码执行结果:

  • 该段代码通过 @CsvFileSource 注释 来提供数据的来源 (适用于有大量测试用例的情况)

使用 @CsvFileSource 注释 的 操作步骤:

1. 在 resources 文件夹下创建后缀名为 .csv 的文件

2.在 @CsvFileSource 注解中,写上新创建的文件名字

 3.点开新创建的文件,进行数据编写,每行代表 一个 name 参数,传入测试方法中

 


多参数

public class JunitTest {

    @ParameterizedTest
    @CsvSource({"1, 2, ''"}) // z 为一个空字符串且能被打印
    void Test08(String x,String y,String z) {
        System.out.println(x);
        System.out.println(y);
        System.out.println(z);
        System.out.println("======================");
    }

    @ParameterizedTest
    @CsvSource({"小林,18", "小王,20"}) 
    void Test10(String name, String age) {
        System.out.println(name +" " + age);
    }
}

该段代码执行结果:

  •   该段代码 通过 @CsvSource 注释 来提供数据的来源
  • @CsvSource 注释中的 每一个双引号就是一组参数

动态参数

public class JunitTest {

    @ParameterizedTest
    @MethodSource("Generator")//相匹配的方法必须为静态方法
    void Test07(String str, int num) {
        System.out.println(str + ":" + num);
    }
    /*
        注意:
        1.首先方法必须为 静态方法
        2.如果返回的数据类型时同一的,直接写该具体类型
          如果不统一,需要使用组合类型 Arguments
    */
    public static Stream<Arguments> Generator() throws InterruptedException {
        String[] arr = new String[3];
        for (int i = 0; i < 3; i++) {
//            这里加上 强制等待 是因为 该循环执行速度太快 时间戳 变化不明显 
            sleep(500);
            arr[i] = System.currentTimeMillis() + "";
        }
        return Stream.of(Arguments.arguments(arr[0],1),
                Arguments.arguments(arr[1],2),
                Arguments.arguments(arr[2],3));
    }
}

该代码执行结果:

  • 该段代码 通过 @MethodSource 注释 来提供数据的来源
  • 作为动态参数我们可以写一个包含时间戳的静态方法来创建变化的数据
  • 静态方法作为数据源的同时,也是 @MethodSource 注释 的参数

测试套件 

指定类名来运行类下的所有用例

JuniteTest 类:

public class JunitTest {

    @Test
    void Test01() {
        System.out.println("这是 JuniteTest 里面的 Test01");
    }
}

JuniteTest2 类:

public class JunitTest2 {

    @Test
    void Test01() {
        System.out.println("这是 JunitTest2 里面的 Test01");
    }
}

RunSuite 类:

@Suite
//这里的测试用例类 按照我们所写的 class 的一个顺序来进行执行的
@SelectClasses({JunitTest.class,JunitTest2.class})
public class RunSuite {
}

该段代码执行结果: 

  • 新创建一个 RunSuite 类
  • 通过 @Suite 注解 声明该类为测试套件类(不是测试类)
  • 我们便可通过 @SelectClasses 注解来自定义 测试类的执行顺序
  • 所运行的测试方法 必须使用 @Test 注解

指定包名来运行包下的所有用例

package01 包:

package package01;

public class Test01 {

    @Test
    void test01() {
        System.out.println("这是 包:package01 类:Test01 中的 test01 方法");
    }
}

package02 包:

package package02;

import org.junit.jupiter.api.Test;

public class Test02 {
    @Test
    void test02(){
        System.out.println("这是 包:package02 类:Test02 中的 test02 方法");
    }
}

RunSuite 类:

@Suite
//这里的测试用例类 按照我们所写的 package 的一个顺序来进行执行的
@SelectPackages(value = {"package02", "package01"})
public class RunSuite {
}

该段代码执行结果: 

  • 新创建一个 RunSuite 类
  • 通过 @Suite 注解 声明该类为测试套件类(不是测试类)
  • 我们便可通过 @SelectPackages 注解来自定义 测试类的执行顺序
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

茂大师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值