Junit 5 单元测试框架

Posted Master_hl

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Junit 5 单元测试框架相关的知识,希望对你有一定的参考价值。

目录

1. Junit 5 的依赖

2. Junit - 注解

2.1 @Test

2.2 @BeforeEach

2.3 @BeforeAll

2.4 @AfterEach

2.5 @AfterAll

3. Junit - 断言

3.1 assertEquals/ assertNotEquals 断言是否匹配

3.2 assertTrue / assertFalse 断言结果的真假

3.3 assertNull / assertNotNull 断言结果是否为空

4. Junit - 测试用例的执行顺序

5. Junit - 参数化

5.1 单参数数据来源

5.2 多参数数据来源 - 在注解里编写数据源

5.3 多参数数据来源 - 从第三方 csv 文件读取数据源

5.4 多参数数据来源 - 通过动态方法来提供数据源

6. JUnit - 测试套件

6.1 指定类来运行用例

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


1. Junit 5 的依赖

<dependency>
    <groupId>org.junit.jupiter</groupId>
    <artifactId>junit-jupiter</artifactId>
    <version>5.8.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-suite</artifactId>
    <version>1.8.2</version>
    <scope>test</scope>
</dependency>

如果之前已经下载过 Junit 4 的相关依赖, 那么则需要先删除本地仓库的依赖, 再下载 Jnit5 的依赖.

2. Junit - 注解

2.1 @Test

该注解是用来加在测试的方法上面的, 表示该方法是测试方法, 并且当我们给方法加上  @Test 注解的时候, 当前方法就可以自己运行了, 不再需要 main 函数来调用. 而且当前类也可以自己运行了 , 运行当前类表示执行当前类里面所有加了 @Test 注解的方法.

不使用 @Test 注解之前, 测试方法需要的步骤 : 

第一步 : 编写测试类, 编写测试方法.

第二步 : 编写运行测试类, 添加 main 方法, 实例化测试类, 调用相关测试方法.

 

使用 @Test 注解之后, 测试方法需要的步骤 : 

由此对比, 使用 Junit 提供的注解来辅助自动化测试, 大大简化了代码的编写, 更加的方便了测试人员更好的进行测试.

并且, 在一个测试类中, 你想让哪些方法执行, 就在该方法上加 @Test 注解即可, 不想让它执行, 就去掉 @Test 注解即可, 非常方便.

 执行结果 : 

2.2 @BeforeEach

该注解是修饰方法的, 当一个测试方法加上 @BeforeEach 注解之后, 就表示当前方法需要在每个测试用例执行之前都执行一次. (注意加上 @BeforeEach 注解之后, 就不要加 @Test 注解了)

代码示例 : 

public class JunitTest 
    @BeforeEach
    void baseController() 
        System.out.println("before each");
    
    @Test
    void base1() 
        System.out.println("bbb");
    
    @Test
    void base2() 
        System.out.println("ccc");
    

执行结果 : 

2.3 @BeforeAll

该注解是修饰方法的, 当一个测试方法加上 @BeforeAll 注解之后, 就表示当前方法需要在当前类下所有测试用例执行之前执行一次. 并且被该注解修饰的方法必须为静态方法. 

在测试项目的时候, 可以把创建驱动对象单独写一个方法, 使用 @BeforeAll 注解修饰. 

代码示例 : 

public class JunitTest 
    @BeforeAll
    static void baseController() 
        System.out.println("before all");
    
    @Test
    void base1() 
        System.out.println("bbb");
    
    @Test
    void base2() 
        System.out.println("ccc");
    

执行结果 :

2.4 @AfterEach

该注解是修饰方法的, 当一个测试方法加上 @AfterEach 注解之后, 就表示当前方法需要在每个测试用例执行之后都执行一次.

代码示例 : 

public class JunitTest 
    @AfterEach
    void baseController() 
        System.out.println("after each");
    
    @Test
    void base1() 
        System.out.println("bbb");
    
    @Test
    void base2() 
        System.out.println("ccc");
    

执行结果 :  

2.5 @AfterAll

该注解是修饰方法的, 当一个测试方法加上 @AfterAll 注解之后, 就表示当前方法需要在当前类下所有测试用例执行之后执行一次. 并且被该注解修饰的方法必须为静态方法.

在测试项目的时候, 可以把释放驱动对象单独写一个方法, 使用 @AfterAll 注解修饰. 

代码示例 : 

public class JunitTest 
    @AfterAll
    static void baseController() 
        System.out.println("after all");
    
    @Test
    void base1() 
        System.out.println("bbb");
    
    @Test
    void base2() 
        System.out.println("ccc");
    

 执行结果 :

3. Junit - 断言

3.1 assertEquals/ assertNotEquals 断言是否匹配

例如我们获取一下百度首页中百度一下按钮上的文字 - 百度一下, 假如我们的预期结果是百度两下, 而打印的是百度一下, 此时就可以使用 assertEquals 来断言是否匹配. 该方法有两个参数, 第一个参数是预期结果, 第二个参数是实际结果.

代码示例 : 

@Test
void baseAssert() 
    EdgeDriver driver = new EdgeDriver();
    driver.get("https://www.baidu.com");
    // 获取百度一下按钮上属性对应的值 - 百度一下
    String text = driver.findElement(By.cssSelector("#su"))
                                    .getAttribute("value");
    System.out.println("预期结果: 百度两下, 实际结果 : " + text);
    // 断言匹配
    Assertions.assertEquals("百度两下", text); // false
    // 断言不匹配
    // Assertions.assertNotEquals("百度两下", text); // true
    driver.quit();

执行结果 : 

 使用 assertNotEquals 断言不匹配, 程序执行结果 : 

3.2 assertTrue / assertFalse 断言结果的真假

代码示例 : 

@Test
void baseAssert1() 
    Assertions.assertTrue(1 == 1); // true

@Test
void bassAssert2() 
    Assertions.assertTrue(1 == 0); // false

@Test
void bassAssert3() 
    Assertions.assertFalse(1 == 1); // false

@Test
void bassAssert4() 
    Assertions.assertFalse(1 == 0); // true

执行结果 : 

3.3 assertNull / assertNotNull 断言结果是否为空

代码示例 : 

@Test
void baseAssert5() 
    String res = null;
    Assertions.assertNull(res);

@Test
void baseAssert6() 
    String res = "hello";
    Assertions.assertNull(res);

执行结果 :  

4. Junit - 测试用例的执行顺序

先来看默认情况下, 多个测试用例的执行顺序.

代码示例 :

public class JunitTest 
    @Test // 2
    void editLoginTest() 
        System.out.println("loginTest");
    
    @Test // 1
    void indexTest() 
        System.out.println("indexTest");
    
    @Test // 3
    void editTest() 
        System.out.println("editTest");
    

执行结果 : 

从执行结果来看, 默认情况下, 多个测试用例的执行顺序是随机的 (可以调整顺序, 多运行几次) . 那么有时候我们一些登录的场景, 是需要按照顺序进行测试的, 比如说博客的登录系统, 我们要登录之后, 才能进入到博客列表页, 博客编辑页, 此时就需要针对多个测试用例指定执行顺序了.

使用 @Order 注解来指定多个测试用例的执行顺序 : 

1. 先要使用 @TestMethodOrder 注解来说明当前类下所有的用例需要使用 Order 注解来进行排序, 当然也可以根据方法名排序, 但是常用的还是 Order 指定方法排序.

2. 然后通过 @Order 注解来指定测试用例的具体顺序.

3. @Test 注解不能删除.

代码示例 : 

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class JunitTest 
    @Test
    @Order(1)
    void editLoginTest() 
        System.out.println("loginTest");
    
    @Test
    @Order(2)
    void indexTest() 
        System.out.println("indexTest");
    
    @Test
    @Order(3)
    void editTest() 
        System.out.println("editTest");
    

执行结果 : 

5. Junit - 参数化

在登录场景中, 如果我们不使用参数化, 那么多个用户登录的时候, 我们的测试用例写起来就会非常麻烦, 如下 : 

 而我们期望的是尽可能的通过一个测试用例, 多组参数来模拟用户的登录行为.

1. 在使用参数化注解之前需要先使用 @ParamterizedTest 声明该方法为参数化方法.

2. 通过注解提供数据来源.

5.1 单参数数据来源

使用 @ValueSource 注解

@ValueSource(数据类型方法 = 参数1, 参数2, 参数3 .....)

@ParameterizedTest
@ValueSource(strings = "张三", "李四", "王五")
void singleParamTest(String name) 
    System.out.println(name);

执行结果 : 

5.2 多参数数据来源 - 在注解里编写数据源

使用 @CsvSource 注解.

@CsvSource("第一组数据", "第二组数据", "第三组数据", ....) , 每一个双引号, 就是一组测试用例.

@ParameterizedTest
@CsvSource("张三, 123","李四, 123", "王五, 123")
void muchParamTest(String name, int age) 
    System.out.println("name: " + name + ", age : " + age);

执行结果 : 

5.3 多参数数据来源 - 从第三方 csv 文件读取数据源

多参数场景下, 当在注解中的测试用例越来越多时, 代码的可读性就会非常差, 此时可以使用 @CsvFileSource 注解来从第三方 csv 文件中读取数据源.

@CsvFileSource(files = "文件路径")

@ParameterizedTest
@CsvFileSource(files = "D:\\\\aa\\\\abc.csv")
void csvFileParamTest(String name, int age) 
    System.out.println("name: " + name + ", age : " + age);

执行结果 : 

5.4 多参数数据来源 - 通过动态方法来提供数据源

使用 @MethodSource 注解

@ParameterizedTest
@MethodSource("methodParams")
void dynamicMethodParamTest(String name, int age) 
    System.out.println("name : " + name + ",age : " + age);

static Stream<Arguments> methodParams() throws InterruptedException 
    // 构造动态参数
    String[] array = new String[5];
    for(int i = 0; i < array.length; ++i) 
        Thread.sleep(500);
        array[i] = String.valueOf(System.currentTimeMillis());
    
    return Stream.of(
            Arguments.arguments(array[0], 21),
            Arguments.arguments(array[1], 22),
            Arguments.arguments(array[2], 23),
            Arguments.arguments(array[3], 24),
            Arguments.arguments(array[4], 25)
    );

执行结果 : 

此处指定的方法的返回类型 Arguments, 是因为一组数据的数据类型不同, 由 String 和 int 类型组合来的, 因此要使用组合类型  Arguments. 如果相同, 就可以写具体的类型.

【其他注意事项]

1. 当我们不指定数据源方法名时, 会自动的找跟用例方法名同名的静态方法.

2. 使用了参数化注解的方法不能再用 @Test 注解. (@Test 只能作用在非参数化的用例上)

6. JUnit - 测试套件

测试套件是用来指定当前包下哪些类中测试方法需要被执行, 如果没有测试套件, 我们很难去同时执行几个类下的测试用例. 

准备工作 : 在 autoTest5 包下创建 aaa, bbb, ccc, 三个测试类, 分别给每个类加上测试方法,  以及前面创建好的 JunitTest 测试类. 

6.1 指定类来运行用例

创建 runSuite 测试套件类, 添加@Suite注解, @SelectClasses 注解, 指定类运行类下的加了 @Test 注解, 或者参数化的测试用例.

@Suite
@SelectClasses(aaa.class,ccc.class)
public class runSuite 

运行测试套件, 执行结果 : 

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

此时 autoTest5 包下有如下几个类 : 

 改写测试套件代码 : 

@Suite
@SelectPackages("com.autoTest5")
public class runSuite 

执行结果 : 

 autoTest5 包下明明有 4 个类, 为啥只运行了一个类中的测试用例呢 ? 

如果使用包名来指定运行的范围, 那么该包下所有测试类的命名必须要以 Test/Tests 结尾 (T 必须要大写)

改类名 : 

 执行结果 : 


本篇文章就到这里了, 谢谢观看~

junit-单元测试

一.JUnit简介

JUnit 是一个 Java编程语言的单元测试框架。JUnit 在测试驱动的开发方面有很重要的发展,是起源于 JUnit 的一个统称为 xUnit 的单元测试框架之一。

 

JUnit 是一个回归测试框架,被开发者用于实施对应用程序的单元测试,加快程序编制速度,同时提高编码的质量。JUnit 测试框架能够轻松完成以下任意两种结合:

  • Eclipse 集成开发环境
  • Ant 打包工具
  • Maven 项目构建管理

二.JUnit使用

JUnit是程序员自己测试多个方法的单元测试框架 使用格式必须为 public void 方法名(){} 可以抛出异常

JUnit常用的注解  方法类型public static void

@BeforeClass 在测试类里所有用例运行之前,运行一次这个方法

@AfterClass  跟@BeforeClass对应,在测试类里所有用例运行之后,运行一次。用于处理一些测试后续工作,例如清理数据

JUnit可以和框架整合,更高效的测试 @RunWith

三.为什么使用JUnit测试

在程序里边,一个接口对应一个实现方法,而在接口中常常会定义相关的很多方法,所以在测试的时候,如果都在main方法里边进行测试,main方法就会显得臃肿,而且不便于以后其他人测试以及查看测试数据,用Junit Test测试的话,一个方法对应一个测试方法,简单明了,也方便别人查看测试方法以及测试数据。

四.总结

Junit是测试执行的开始阶段,即首先对每一个程序模块进行单元测试,以确保每个模块能正常工作。单元测试是程序员对自己的代码进行测试后,所以是大多是白盒测试。JUnit的最大作用就是可以方便的进行单个方法的测试。可与其他框架整合方便了JUnit的使用。

 

以上是关于Junit 5 单元测试框架的主要内容,如果未能解决你的问题,请参考以下文章

junit-单元测试

-单元测试框架-Junit

-单元测试框架-Junit

为什么使用Junit单元测试?Junit的详解

为什么使用Junit单元测试?Junit的详解

Spring—— Junit框架单元测试