DSL domain specific language of Kola

news2024/9/24 15:26:32

 

 How we design Kola - ApiHugKola background, Kola a consumer driver tester frameworkicon-default.png?t=N7T8https://apihug.com/zhCN-docs/kola/003_dsl_contract

Concept

在 Kola 定位中 Kola 是什么, 是致力于提供一个让相关各方都能够理解共同创造的测试框架和工具。

同时 Kola 是建立于业界成熟的实践和方法论上,综合工程实践的便利和流程的严谨性, 在主流的测试思想中,这三种 Kola 深受启发:

  1. TDD: Test driven development
  2. BDD: Behaviour-Driven Development
  3. CDC: Consumer Driven Contracts

在工程实践中; Kola 从 SmartBear 的 PactFlow, Spring clout Contract, Spock, Karate 等前辈上得到很多参考和灵感;

更不用说, 测试界的基石: Junit5, TestNG, AssertJ 等基础框架;

Kola 一如既往遵循软件开发的开闭原则, 在学习成本、工程实践、团队协同上做综合的调和, 让整个测试过程更丝滑,更人性化:

Kola make your test life happier and colourful

为什么 BDD 风格声明为首选? 虽然我们没有使用主流 BDD 实践框架比如 Cucumber, 作为底座;

但是 BDD 的表达方式,真的是太好了,兼顾程序世界的结构化,和非程序世界的通俗易懂;所以用他来表达用户用例(故事)再好不过!

Feature: Explaining ApiHug
  In order to gain an understanding of the ApiHug testing system
  As a non-programmer
  I want to have an overview of ApiHug that is understandable by non-geeks

  Scenario: A worker seeks an overview of ApiHug 
    Given I have a coworker who knows a lot about ApiHug
    When I ask my coworker to give an overview of how ApiHug works
    And I listen to their explanation
    Then I should have a basic understanding of ApiHug

这个来自官方的标准BDD 定义方式, 在 Kola 概念基本暴利, 除了 And 被省掉;

因为一般我们是 request, response 方式验证API, And 就是发送请求, Then 直接对结果验证。

Kola, 协议定义在: import hope.kola.contract.Feature 使用 groovy 语法, 让整体的用例书写更轻松和愉悦。

👍 如果你的 Feature Groovy 在IDE未能识别, 在更新版本后尝试 Reload gradle 以让IDE刷新识别。

​Background

A Background allows you to add some context to the scenarios that follow it. It can contain one or more Given steps, which are run before each scenario, but after any Before hooks.

​Feature

The purpose of the Feature keyword is to provide a high-level description of a software feature, and to group related scenarios.

​Scenario

a written description of your product’s behavior from one or more users’ perspectives

​Given

Given steps are used to describe the initial context of the system - the scene of the scenario. It is typically something that happened in the past.

在 ApiHug 上下文, Given 就是 API 环境, 可以从 ApiHug 或者独立的API 环境引入:

​ApiHug API

这个是最直接的方式:

    Given {
        api("UserService", "Login")
    }
  1. UserService ApiHug 服务, 最好全路径引入, 编译时会校验, 相对路径也可以, 但是保证无重复, IDEA 提供工具自动化完成
  2. Login 方法名, 在此服务内必须包含

直接用 ApiHug 上下文的 api 可以有更丰富的上下文, 关于request, response 的定义, path, 参数, 校验规则。

request body 预 mock, 无须自己写 body, 只需稍微调整就可以。

是 kola 首推的方式!

​Raw API

如果第三方的API, 我们没有的元信息,只能通过手动写:

    Given {
        get("https://github.com")
    }

​When

When steps are used to describe an event, or an action. This can be a person interacting with the system, or it can be an event triggered by another system.

在 ApiHug 的定义中, When 用来组装 request 的上下文:

类型备注
body请求体,可以通过json, 然后通过生命式语法动态声明
multipart附件
cookiescookie 信息
headersheader 信息
queries请求参数(动态)
paths路径参数(动态)
​请求体

JSON 定义:

    json("""
{
   "name": "jake",
   "age": 18,
   "address": {
     "country": "$V('from')",
     "zip": 200021
   }
}
""")
  1. 标准 json 定义方式
  2. 动态环境变量 $V('from') 运行时会通过 expression 从环境中获取 from 参数值;

body 修改:

定义完成后如果还不能满足需求,可以继续通过 body 进行 json path 进一步修改, 修改和覆盖原来值;

  body {
      set('name', "same")
      set('student.name', "blue")
      set('student.age', 22)
      set('student.weight', 123.3d)
      set('student.friends', "jake", "blue", "yellow")
      fromGlobal("student.country", "country")
  }

最终组装成一个合适的请求体;

​multipart
  multipart {
      file{
        fromClassPath("hello.txt")
      }
  }
​cookies
    cookies {
        //Possible Bear + {jwt}
        fromGlobal(authorization(), "jwt")
    }
​headers
​queries
  queries {
      pageable {
          page(0)
          size(12)
      }
      fromGlobal("userName", "jake")
  }
​paths
  paths {
      fromGlobal("user-id", "userId")
  }

​Then

Then steps are used to describe an expected outcome, or result.

​status
  Then {
      isOk()
      status 200
  }
​body
    stringAssert("user.address.zipCode", {
        isEqualTo("jake")
        isBase64()
        isAlphabetic()
        startsWithIgnoringCase("json")
    })
    bigDecimalAssert("user.salary", {
        isCloseTo(new BigDecimal("1112.22"), Offset.offset(12))
        isGreaterThanOrEqualTo(new BigDecimal("231312"))
    })
    booleanAssert("user.live", {
        isTrue()
    })
  1. 基于 json path
  2. Assertj Assertions 全部 bridge, Fluent assertions
  3. 声明式校验,一写到底,一气呵成

​Script Support

​Pre Script

​Post Script

    postScript {
        {
            headSet("age", 1234)
            globalSet("same", "blue")
        }
    }

​Junit

Consumer Driven Contracts, What’s Kola’s domain language looks like?

How it easy to understand and get hand in. you will love it.

Default Extension, lifecycle management.

​Configuration

Use DSL to define environment also {WIRE_MODULE}/src/test/resources/config/kola.groovy:

  1. common: base configuration
  2. different env overwrite configuration property
  3. active env base on the passed env flag: -Dtags=qa,dev
import com.test.bigger.example.Student
import static hope.kola.contract.Configuration.*

var big = 1123

[
        common {
            baseURI("https://qa.example.com")
            port(9527)
            p("date", ofDate("2022-12-12"))
            rest {
                log {
                    enablePrettyPrinting()
                    logBodyDetailIfValidationFails()
                }
            }

        },

        env("qa", {

            baseURI("https://qa.example.com")
            port(big)

        }),

        env("prod", {

            baseURI("https://prod.example.com")
            p("date", nowDayOfMonth())
            p("bigStudent", new Student().setName("jake").setAge(19))
            rest {
                closeIdleConnectionsAfterEachResponse(12l, second())
                log {
                    logAllDetailIfValidationFails()
                }
            }
        })
]

​Sample

import hope.kola.contract.Feature
import org.assertj.core.data.Offset

Feature.make {
    priority 100
    name("Customer login place order and check balance logic")
    description("""Never judge the boss, as you may the real fool""")
    Scenario "001 Try login ", {
        preScript {
            //Define prepare logic here
        }
        Given {
            api("UserService", "Login")
        }
        When {
            json("""
                    
            """)
            body {
                set('name', "same")
                set('student.name', "blue")
                set('student.age', 22)
                set('student.weight', 123.3d)
                set('student.friends', "jake", "blue", "yellow")
                fromGlobal("student.country", "country")
            }
            queries {
                pageable {
                    page(0)
                    size(12)
                }
                fromGlobal("userName", "jake")
            }
            paths {
                fromGlobal("user-id", "userId")
            }
        }
        And {
            stringAssert("user.address.zipCode", {
                isEqualTo("jake")
                isBase64()
                isAlphabetic()
                startsWithIgnoringCase("json")
            })
            bigDecimalAssert("user.salary", {
                isCloseTo(new BigDecimal("1112.22"), Offset.offset(12))
                isGreaterThanOrEqualTo(new BigDecimal("231312"))
            })
            booleanAssert("user.live", {
                isTrue()
            })

        }
        postScript {
            {
                headSet("age", 1234)
                globalSet("same", "blue")
            }
        }

    }
    Scenario "002 Place a order", {}
    Scenario "003 Check balance", {}
}

​参考

  1. spring test spring-framework/spring-test
  2. spring test doc spring-framework/reference/testing
  3. spring boot test spring-boot-test
  4. spring boot test doc spring-boot/testing
  5. spring contract spring-cloud-contract
  6. spring contract doc spring-cloud-contract reference
  7. cucumber Behaviour-Driven Development
  8. Spock: Spock Framework
  9. karate Test Automation Made Simple
  10. Contract Test Martin Fowler
  11. PactFlow SmartBear Consumer Driven
  12. Contract Testing Vs Integration Testing from PactFlow
  13. Consumer-Driven Contracts: A Service Evolution Pattern

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1993299.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AcWing双链表

0索引记录头结点,1索引是尾节点,idx从2开始记录 L和R是前面的索引和后面索引的数组,e是存储的元素的数组,k1的原因:k是表示第k个插入的元素, k ∈ [ 1 , inf ⁡ ] k\in [1,\inf] k∈[1,inf].但是 i d x ∈ …

卷爆大模型,引发硅谷大厂打擂台赛的AI Agent到底是何方神圣?

AI Agent是何方神圣? 让比尔盖茨在2023年预言:未来五年内有望正式迎来它,彻底改变人类的生产力与生活方式。 让吴恩达教授在AI Ascent 2024演讲中高赞:今年得益于它的工作流的帮助, 人工智能的能力范围将持续拓展&am…

VBA经典应用69例应用6:Range.NumberFormat属性

《VBA经典应用69例》(版权10178981),是我推出的第九套教程,教程是专门针对初级、中级学员在学习VBA过程中可能遇到的案例展开,这套教程案例众多,紧贴“实战”,并做“战术总结”,以便…

2023年中国城市统计年鉴(PDF+excel)

2023年中国城市统计年鉴 1、时间:1985-2023年 2、格式:PDFexcel 3、说明:中国城市统计年鉴收录了全国各级城市社会经济发展等方面的主要统计数据,数据来源于各城市的相关部门。本年鉴内容共分四个部分:第一部分是全…

HDFS 之 文件流

org.apache.hadoop.hdfs.DFSInputStream read 接口的关键逻辑在以下 pread 接口。 private int pread(long position, ByteBuffer buffer)throws IOException {// sanity checksdfsClient.checkOpen();if (closed.get()) {throw new IOException("Stream closed");}…

24/8/8算法笔记 决策树构建鸢尾花

决策树是一种由算法自动设计的模型。在机器学习中,构建决策树的过程通常遵循以下步骤: 特征选择:算法会评估每个特征,并选择一个特征作为节点分裂的依据。这个选择基于某种准则,如信息增益(ID3算法&#xf…

手把手教你去掉WinRAR中的广告?

你是否在使用WinRAR的时候,打开压缩包的时候,它就会给你弹出一个广告窗口,是不是很烦人。本章教程,教你如何将它去除掉。 1、下载所需软件 通过百度网盘分享的文件:reshacker 链接:https://pan.baidu.com/s…

基础复习(前端部分)

MVVM(Model-View-ViewModel)的前端开发思想 Model: 数据模型,特指前端中通过请求从后台获取的数据 View: 视图,用于展示数据的页面,可以理解成我们的htmlcss搭建的页面,但是没有数据 ViewModel: 数据绑定到视图,负责…

SQL Server端口设置完整详细步骤

​ 大家好,我是程序员小羊! 前言: 前面是对SQLserver服务器一些介绍,不想了解的可直接点击目录跳入正题,谢谢!!! SQL Server 是由微软公司开发的关系数据库管理系统 (RDBMS)。它主要…

伪原创改写软件,最便捷的改文章选择

说到改文章,很多人的直接想法就是自己动手去修改,但自己动手改文章的过程中是需要花大量时间阅读并理解透文章写的意思,然后才便于修改,然而伪原创改写软件的出现却在修改文章的工作中提供了非常大多的作用,不管是节省…

揭秘人工智能三大基石:数据、算法与算力的深度融合

在科技日新月异的今天,人工智能(AI)作为引领未来科技浪潮的核心力量,正以前所未有的速度改变着我们的生活、工作乃至整个社会的面貌。人工智能的快速发展并非偶然,而是建立在三大坚实基石之上:数据、算法与…

Nacos-配置中心

1.为什么要使用配置中心&#xff1f; 2.常用的配置中心组件&#xff1f; 3.如何使用&#xff1f; 在配置中心创建配置文件 启动一个单列的nacos服务 点击发布 在微服务中使用 添加依赖 <!--nacso配置中心的依赖--><dependency><groupId>com.alibaba.cloud&l…

zdppy+vue3+onllyoffice开发文档管理系统项目实战 20240808 上课笔记

遗留的问题 1、实现删除的功能 2、分享的功能暂时往后放&#xff0c;因为目前没有用户&#xff0c;等有了用户之后再考虑做 3、增加新建和导入按钮 zdppy的学习计划 机器学习平台&#xff0c;QQ音乐的开源项目&#xff0c;https://github.com/tencentmusic/cube-studio&#…

Python语法基础常识

01 #中英文格式问题 我们用Python编程时用到的所有字母、符号、函数格式等都应当使用英文格式。 不少同学在刚入门的时候&#xff0c;可能会因为用错格式而频频报错、运行失败&#xff0c;这就需要我们时刻留意啦。 02 #print函数的使用 print函数会是我们接触Python时第一个…

万字解析文件fd,深刻理解:fd文件描述符、位图、标准输入、标准输出、标准错误、文件打开、文件关闭、Linux一切皆文件理解、进程和文件的关系、虚拟软件系统

建议全文阅读&#xff01;&#xff01;&#xff01; 建议全文阅读&#xff01;&#xff01;&#xff01; 建议全文阅读&#xff01;&#xff01;&#xff01; 目录 文章概述 一、文件操作 1、什么叫当前路径 2、常见文件操作 &#xff08;1&#xff09;fopen函数 &…

YASKAWA安川直驱电机DD马达Σ-7系列介绍

随着智能制造的兴起&#xff0c;对设备精度、效率及可靠性的要求日益提升&#xff0c;安川Σ-7系列无需减速机即可直接驱动负载的“直驱伺服电机”&#xff0c;以其独特的优势正逐步成为众多高精度、高效率应用场景下的运动控制解决方案。 一、直驱技术的革命性突破 传统伺服…

When can a sum and integral be interchanged?

https://math.stackexchange.com/questions/83721/when-can-a-sum-and-integral-be-interchanged https://math.stackexchange.com/questions/1334907/reversing-the-order-of-integration-and-summation

【大模型从入门到精通12】openAI API 提示链的力量3

这里写目录标题 实践问题 实践部分场景概述场景步骤初始产品询问故障排除请求保修问题额外产品推荐 示例实现 实践问题 编写一个名为retrieve_model_response的Python函数&#xff0c;该函数接受一个消息序列作为输入&#xff0c;并根据给定参数返回模型的响应。包括模型、温度…

如何去掉el-input自带边框

<style lang"scss" scoped>::v-deep .inputDeep .el-input__inner {border: none !important;box-shadow: none !important;padding: 0px; }</style> //先定义一个类名 <el-input v-model"form.name" class"inputDeep"><…

7.3.1.算法设计与分析-总结及真题讲解

总结 分治法特征&#xff1a;把一个问题拆分成多个小规模的相同子问题&#xff0c;一般可用递归解决。 经典问题&#xff1a;斐波那契数列、归并排序、快速排序、矩阵乘法、二分搜索、大整数乘法、汉诺塔 回溯法特征&#xff1a;系统的搜索一个问题的所有解或任一解。 经典问题…