项目-Java-Junit-Lua

文章目录

    • 参考内容
    • 接口的本质
      • 基础
      • HTTP接口
    • Junit5
      • 基础内容
      • 测试注解
      • 断言
      • 前置条件
      • 嵌套测试
      • 参数化测试
      • 项目学习
    • 与JUnit4的显著区别
    • Lua
      • 概述

参考内容

testNG教程:
https://zhuanlan.zhihu.com/p/623245201
maven项目创建教程:
https://blog.csdn.net/m0_68857031/article/details/129842135
junit5官方文档:
https://doczhcn.gitbook.io/junit5/index

接口的本质

基础

接口是服务,是代码实现的一段业务逻辑,如:登录接口、认证接口;
服务可以是任意协议(https、dubbo、webService),业务逻辑实现方式为任意语言(java、python、C++)
接口测试只需要关注对应协议,无需关注后台实现语言。

HTTP接口

一般接口协议大都数为HTTP协议;
HTTP协议的特点:
分为客户端和服务端,客户端发送请求,服务端返回响应结果;
客户端发送的请求包括:URL = 接口地址,请求方式 = psot/get/delete/put/patch,请求参数 = 根据接口文档填写
服务器返回的响应包括:响应头, 响应体(json格式或其他格式);

Junit5

基础内容

  • Junit5由JUnit Platform + JUnit Jupiter + JUnit Vintage3部分构成。
    JUnit Platform:其主要作用是在 JVM 上启动测试框架,是运行在平台上的测试框架,其他自动化测试引擎以及开发人员定制的测试引擎可以接入JUnit5实现对接与执行;
    JUnit Jupiter:提供了JUnit5 新的编程模型,是JUnit5新特性的核心,内部包含了一个测试引擎;
    JUnit Vintage3:提供了兼容JUnit4.x,Junit3.x的测试引擎。
  • springboot 结合JUnit测试
    需要在pom.xml中引入依赖;创建测试类,添加@SpringbootTest注解以及@Test注解;
    依赖项是:org.springframework.boot:spring-boot-starter-test
    当前项目使用的测试代码不是采用Springboot实现的测试,而是直接导入JUnit测试包实现的。

测试注解

@Test : 标识测试方法;
@DisplayName : 为测试类或者测试方法 设置展示的名字
@BeforeEach :每个单元测试前执行
@AfterEach:每个单元测试后执行
@BeforeAll :所有单元测试前执行
@AfterAll :所有单元测试后执行
@Tag :单元测试的级别
@Disabled :测试类或测试方法不执行
@Timeout :测试方法运行超过制定时间返回错误
@ExtendWith :给测试类或测试方法提供扩展类引用
@ParamterizedTest :方法是参数化测试
@RepeatedTest :方法可重复执行

注意:

  • xxxEach和xxxAll区别
    前者表示每个测试用例开始和结束位置需要执行的内容;
    后者表示整个测试用例组执行前或执行后需要展示的内容;

  • xxxAll使用
    由于该注解修饰内容仅会被调用一次,如果不加限制则会报错;
    解决:被标注为静态方法,即需要存在static关键词。

  • Timeout使用
    需要添加参数value = 超时的数值设定,unit = 超时单位设设定;
    超时会报错误,返回TestTimeout() timed out after 500 microseconds

  • ExtendWith使用
    使用场景:使用springboot的容器功能,使用@SpringbootTest注解,它是组合注解,包括
    @ExtendWith(SpringExtension.class)
    @BootstrapWith(SpringBootTestContextBootstrapper.class)
    那么整个过程就是采用Springboot的测试驱动来测试。如果想对接别的平台,就需要对ExtendWith(SpringExtension.class)做定制开发;

  • RepeatedTest使用
    当和Test注解同时存在时,会报注解竞争异常。

断言

用于检测测试方法返回结果是否满足预取设置结果。
所有测试方法执行结束之后会产生测试详细的测试报告来检查当前测试的情况。
断言分为:简单断言、数组断言、组合断言、异常断言、超时断言、快速失败;

  • 整体特性
    测试方法中存在多个断言,当某个断言运行异常时,则后续代码均不执行;
    断言中两个参数分别是:期望值,真实值;且都可以加三个值,则第三个为自定义错误信息;

简单断言
assertEquals : 判断两个对象或原始类型是否相等
assertNotEquals : 判断两个对象或原始类型是否不相等
assertSame :判断两个对象引用是否指向同一个对象
assertNotSame : 判断两个对象引用是否只想不同的对象
assertTrue :判断给定的布尔值是否为true
assertFalse :判断给定的布尔值是否为false
assertNull :判断给定的对象引用是否为null
assertNotNull :判断给定的对象引用是否不为null

  • assetEquals使用
    调用采用Assertion.assertEquals 方式,因为该方法是静态方法;
    方法参数有两个,分别是(期待值,真实值);
    默认异常提示是:org.opentest4j.AssertionFailedError:
    该方法支持三个参数时,最后一个参数是 自定义错误提示信息;

数组断言
assertArrayEquals : 判断两个数组是否相等,针对每个位置进行匹配;

new int[]{1,2} new int[]{2,1} 这两个数组就不相等

组合断言
assertAll :可以添加多个断言,全部通过之后才成功;多个断言采用lamda表达式实现;

assertAll("给该断言起个名字",
() -> assertxxx(),
() -> assertxxx());

多个断言都成功,组合断言才会成功;
组合断言没有自定义异常描述,可以对其中的多个断言分别加描述信息。

异常断言
assertThrows : 断定测试方法一定会出现某异常。

Assertions.assertThrows(异常类,() -> 具体内容, "自定异常信息");

如果出现异常,则正常执行;反之,则报错,

org.opentest4j.AssertionFailedError: 正常执行? ==> Expected java.lang.ArithmeticException to be thrown, but nothing was thrown.

超时异常
assertTimeout :程序超过设定时间,则出现异常;
参数可以有三个:1 = 设定超时阈值时间;Duration.ofMillis(1000) 2 = 具体执行操作 3 = 自定义返回异常信息

快速失败
fail :直接将测试方法置于失败,参数为“表示该错误展示信息”
该语句运行,则直接抛出:org.opentest4j.AssertionFailedError: 快速失败

前置条件

assumption:假设,不满足前置条件会使得测试方法的执行终止,
不满足于断言会使得测试方法失败;
方法调用为:Assumption.assumeTrue 和 Assumption.assumeFalse

Assumptions.assumeTrue(Boolean.FALSE);
// org.opentest4j.TestAbortedException: Assumption failed: assumption is not true

嵌套测试

@Nested : 测试类中还有测试类 则需要写这个参数;该注解修饰内层测试类;

  • 注意:
    嵌套测试中,外层的test不能驱动内层测试类的beforeEach/All方法;
    内层的test可以驱动外层测试类的beforeEach/All方法;

  • 案例:

@DisplayName("嵌套测试")
public class TestingAStackDemo {
    Stack<Object> stack;

    @Test
    @DisplayName("new Stack()")
    void isInstantiatedWithNew() {
        new Stack<>();
        assertNull(stack);
//        org.opentest4j.AssertionFailedError: expected: not 
        // 外层测试类执行 并会不驱动内层测试类的BeforeEach方法
    }

    @Nested
    @DisplayName("when new")
    class WhenNew {

        @BeforeEach
        void createNewStack() {
            stack = new Stack<>();
        }

        @Test
        @DisplayName("is empty")
        void isEmpty() {
            assertTrue(stack.isEmpty());
        }
        

        @Test
        @DisplayName("throws EmptyStackException when popped")
        void throwsExceptionWhenPopped() {
            assertThrows(EmptyStackException.class, () -> stack.pop()); // 栈中弹出一个元素
        }

        @Test
        @DisplayName("throws EmptyStackException when peeked")
        void throwsExceptionWhenPeeked() {
            assertThrows(EmptyStackException.class, () -> stack.peek()); // 返回栈顶元素,但不移除它
        }

        @Nested
        @DisplayName("after pushing an element")
        class AfterPushing {

            String anElement = "an element";

            @BeforeEach
            void pushAnElement() {
                stack.push(anElement);
            }

            @Test
            @DisplayName("it is no longer empty")
            void isNotEmpty() {
                assertFalse(stack.isEmpty());
            }
            // 内层测试类的执行 可以驱动外层测试类的BeforeEach方法
            // 该测试方法显示成功,在于 外层测试类的BeforeEach方法创建了一个Stack
            // 而 本层类的BeforeEach方法 存入一个元素 所以stack不为空

            @Test
            @DisplayName("returns the element when popped and is empty")
            void returnElementWhenPopped() {
                assertEquals(anElement, stack.pop());
                assertTrue(stack.isEmpty());
            }
            // 该测试方法显示成功,在于 外层测试类的BeforeEach方法创建了一个Stack
            // 而 本层类的BeforeEach方法 存入一个元素 又将stack中元素弹出,则stack为空;

            @Test
            @DisplayName("returns the element when peeked but remains not empty")
            void returnElementWhenPeeked() {
                assertEquals(anElement, stack.peek());
                assertFalse(stack.isEmpty());
            }
            // 该测试方法显示成功,在于 外层测试类的BeforeEach方法创建了一个Stack
            // 而 本层类的BeforeEach方法 存入一个元素 将stack中第一个元素展示但不取出,则stack不为空;
        }
    }
}

参数化测试

关键注解:ParameterizedTest 表示当前测试方法不是普通测试方法,是参数化测试方法;

实现不同的参数,多次运行测试方法;
ValueSource : 为参数化测试制定入参来源,支持八大基础类以及String类型、Class类型;
NullSource :提供一个null的参数
EnumSource :提供一个枚举入参
CsvFileSource :读取CSV文件内容为参数化测试入参
MethodSource :读取指定方法的返回值作为参数化测试入参

  • 案例:
@ParameterizedTest
    @ValueSource(ints = {1,2,3})
    public void testparameterized(int i){
        System.out.println(i);
    }
    // 运行一次 直接输出 1 2 3

遇见问题

1. 使用@ParameterizedTest出现:
java.lang.Exception: No tests found matching Method testRiskControl(com.unicom.qh.common.redis.RedisApplicationTests) from org.junit.vintage.engine.descriptor.RunnerRequest@1b1426f4

分析:
表明JUnit运行器没有找到与@ParamemberizedTest注解匹配的测试方法。
已使用:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class})
依赖:
导入spring-boot-starter-test
导包:
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

这个问题没有解决,望看到的网友如果知道怎么解决,请留言告知,感恩。

项目学习

1

@RunWith(SpringRunner.class)
// 指定了测试运行器,
// SpringRunner是Spring框架提供的一个测试运行器,它扩展了JUnit的SpringJUnit4ClassRunner,这使得Spring框架的测试能够以Spring应用上下文的形式进行初始化。可以使用依赖注入和事务管理;
@SpringBootTest(classes = {Application.class})
// 指示测试类是一个Spring Boot测试类,它将使用Spring Boot的测试框架进行测试;
// 会加载所有spring boot的bean,创建应用上下文,从而使得测试环境与生产环境尽可能一致。

与JUnit4的显著区别

  • @Test注解
    JUnit4 引入包是 org.Junit
    JUnit5 引入包是 org.Junit.jupiter.Test

Lua

概述

你可能感兴趣的:(java学习,java,junit,开发语言)