当前位置: 首页 > news >正文

DSL domain specific language of Kola

 

 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 ApiHugIn order to gain an understanding of the ApiHug testing systemAs a non-programmerI want to have an overview of ApiHug that is understandable by non-geeksScenario: A worker seeks an overview of ApiHug Given I have a coworker who knows a lot about ApiHugWhen I ask my coworker to give an overview of how ApiHug worksAnd I listen to their explanationThen 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.OffsetFeature.make {priority 100name("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

相关文章:

DSL domain specific language of Kola

How we design Kola - ApiHugKola background, Kola a consumer driver tester frameworkhttps://apihug.com/zhCN-docs/kola/003_dsl_contract Concept 在 Kola 定位中 Kola 是什么, 是致力于提供一个让相关各方都能够理解共同创造的测试框架和工具。 同时 Kola 是建立于业界…...

【RISC-V设计-05】- RISC-V处理器设计K0A之GPR

【RISC-V设计-05】- RISC-V处理器设计K0A之GPR 文章目录 【RISC-V设计-05】- RISC-V处理器设计K0A之GPR1.简介2.设计顶层3.内部结构4.端口说明5.设计代码6.总结 1.简介 通用寄存器(General Purpose Register)是处理器设计中的重要组成部分,在…...

Linux/C 高级——shell脚本

1. shell脚本基础概念 1.1概念 shell使用方式:手动下命令和脚本 脚本本质是一个文件,文件里面存放的是特定格式的指令,系统可以使用脚本解析器翻译或解析指令并执行(它不需要编译)。 shell脚本本质:shell命…...

SpringBoot面试题整理(1)

面试整理 前置知识 ApplicationContextInitializerApplicationListenerBeanFactoryBeanDefinitionBeanFactoryPostProcessorAwareInitializingBean/DisposableBeanBeanPostProcessor 面试题 SpringBoot启动流程IOC容器初始化流程Bean声明周期Bean循环依赖SpringMVC执行流程…...

LVS原理及实例

目录 LVS原理 LVS概念 lvs集群的类型 lvs-nat 解释 传输过程 lvs-dr 解释 传输过程 特点 lvs-tun LVS(Linux Virtual Server)常见的调度算法 防火墙标记(Firewall Marking)结合轮询调度 实战案例 lvs的nat模式配置 …...

Spring统一功能处理:拦截器、响应与异常的统一管理

目录 一.拦截器 二.统一数据返回格式 三.统一异常处理 一.拦截器 拦截器是Spring框架提供的核⼼功能之⼀,主要⽤来拦截⽤⼾的请求,在指定⽅法前后,根据业务需要执⾏预先设定的代码。 也就是说,允许开发⼈员提前预定义⼀些逻辑…...

深入理解小程序的渲染机制与性能优化策略

一、小程序的渲染机制 小程序的渲染机制主要由两部分组成:渲染层和逻辑层。渲染层负责页面的渲染,逻辑层负责处理业务逻辑和数据处理。两者通过一个安全的、高效的通信机制进行数据传输和事件通知。 渲染层:在渲染层,WXML 模板会…...

Linux:多线程(二.理解pthread_t、线程互斥与同步、基于阻塞队列的生产消费模型)

上次讲解了多线程第一部分:Linux:多线程(一.Linux线程概念、线程控制——创建、等待、退出、分离,封装一下线程) 文章目录 1.理解Linux下线程——理解tid2. Linux线程互斥2.1相关概念2.2引入问题分析问题解决思路 2.3L…...

Pandas中`str`对象解析与应用实例

在数据科学领域,字符串操作是数据清洗和处理中不可或缺的一部分。Pandas的str对象为我们提供了一个强大而灵活的字符串操作方法集。本文将深入探讨str对象的各种应用,并通过代码示例和输出展示如何有效地处理字符串数据。 关键词 Pandas, 字符串操作, …...

C语言典型例题29

《C程序设计教程(第四版)——谭浩强》 习题2.6 设圆半径r1.5,圆柱高h3,求圆周长、圆面积、圆球表面积、圆球体积、圆柱体积。 scanf输入结果,输出计算结果,输出时要有文字说明,取小数点后两位数…...

Docker 常规安装简介

Docker常规安装简介 欢迎关注我的B站:https://space.bilibili.com/379384819 1. 安装mysql 1.1 docker hub上面查找mysql镜像 网址: https://hub.docker.com/_/mysql 1.2 从docker hub上(阿里云加速器)拉取mysql镜像到本地标…...

理解张量拼接(torch.cat)

拼接 维度顺序:对于 3D 张量,通常可以理解为 (深度, 行, 列) 或 (批次, 行, 列)。 选择一个dim进行拼接的时候其他两个维度大小要相等 对于三维张量,理解 torch.cat 的 dim 参数确实变得更加抽象,但原理是相同的。让我们通过一…...

指针基础知识(笔记)

文章目录 1. 概念理解2. 空指针和野指针3. 计算4. 小结5. size_t6. 案例一: 指针查找并返回指定元素索引7. 指针访问多维数组(涉及 int (*ptr)[3]解析)8. 指针数组9. 函数的值传递与地址引用传递① 函数的值传递(pass by value)② 地址传递(pass by reference) 10. 案例二&…...

[Python学习日记-3] 编程前选择一个好用的编程工具

[Python学习日记-3] 编程前选择一个好用的编程工具 简介 PyCharm IDE的安装 PyCharm IDE安装后的一些常规使用 简介 在踏上 Python 编程的精彩旅程之前,选择一款得心应手的编程工具无疑是至关重要的一步。这就如同战士在出征前精心挑选趁手的武器,它将…...

智能化的Facebook未来:AI如何重塑社交网络的面貌?

随着人工智能(AI)技术的飞速发展,社交网络的面貌正在经历深刻的变革。Facebook(现Meta Platforms)作为全球最大的社交媒体平台之一,正积极探索如何利用AI技术来提升用户体验、优化内容管理并推动平台创新。…...

安全启动的原理

安全启动(Secure Boot)是一种用于确保设备只运行经过认证的软件的安全机制。其核心原理和步骤如下: 1. **硬件信任根(Root of Trust, RoT)**: - 安全启动过程始于硬件信任根,通常是设备上的…...

【ML】pre-train model 是什么如何微调它,如何预训练

【ML】pre-train model 是什么如何微调它,如何预训练 0. 预训练模型(Pre-trained Model)0.1 预训练模型的预训练过程0.2 如何微调预训练模型0.3 总结 1. Contextualized word Embedding2. 怎么 让 bert 模型变小3. 如何微调模型 0. 预训练模型…...

leetcode代码练习——Java的数据结构(具体使用)

注&#xff1a;Java中所有的泛型必须是引用类型 如<Integer>而不是<int> java提供的数学方法&#xff1a; 求最大值Math.max(10,15)&#xff0c;最小值Math.min(10,15) 看取值范围&#xff1a; int范围:-2^31-2^31-1 double范围:-2^63-2^63-1 long范围:-2^63-2…...

sqlserver导出数据脚本

文章目录 sqlserver导出数据脚本任务-生成脚本 sqlserver导出数据脚本 任务-生成脚本...

html+css 实现hover中间展开背景

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽效果&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目…...

MySQL大小写规则与存储引擎详解

目录 MySQL在Linux下数据库名、表名、列名、别名大小写规则 SQL编写建议&#xff1a; 默认数据库里都是什么内容&#xff1f; &#xff08;1&#xff09;mysql &#xff08;2&#xff09;information_schema &#xff08;3&#xff09;performance_schema &#xff08;4…...

OpenClaw沙盒方案:千问3.5-35B-A3B-FP8云端测试环境搭建

OpenClaw沙盒方案&#xff1a;千问3.5-35B-A3B-FP8云端测试环境搭建 1. 为什么需要沙盒测试环境 上周我在尝试将OpenClaw接入本地部署的千问模型时&#xff0c;遇到了一个典型问题&#xff1a;模型推理占用了大量显存&#xff0c;导致我的开发机几乎无法进行其他操作。更糟的…...

【C】static

static1、修饰局部变量&#xff1a;使其变为静态变量&#xff0c;这个局部变量在函数执行完成后不会被释放&#xff0c;而是继续保留在内存里。2、修饰全局变量&#xff1a;使其只在本文件内部有效&#xff0c;在其他文件不可用。3、修饰函数&#xff1a;使函数只能在本文件中使…...

2025届必备的五大降AI率方案推荐

Ai论文网站排名&#xff08;开题报告、文献综述、降aigc率、降重综合对比&#xff09; TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 在内容创作这个范畴里&#xff0c;要提升文本的真实感以及原创性&#xff0c;关键在于降低人…...

为什么93%的团队在Python 3.14 JIT上线后性能反降?深度解析JIT热路径识别失效与类型推测崩塌链

第一章&#xff1a;Python 3.14 JIT编译器性能反降现象的全局观测与归因定位近期多个基准测试套件在 Python 3.14 alpha 版本中观测到显著的性能退化&#xff0c;尤其在 CPU 密集型循环与协程调度场景下&#xff0c;pystone、pyperf benchmarks 的吞吐量平均下降 12.7%&#xf…...

为什么你的STM32 DMA传输失败了?__HAL_LINKDMA宏的隐藏陷阱与解决方案

为什么你的STM32 DMA传输失败了&#xff1f;__HAL_LINKDMA宏的隐藏陷阱与解决方案 在STM32开发中&#xff0c;DMA&#xff08;直接内存访问&#xff09;传输是提升外设数据吞吐效率的关键技术。然而&#xff0c;许多开发者在实际项目中都会遇到DMA传输失败的问题&#xff0c;而…...

gpu算力与图形处理

核心本质 图形处理&#xff08;Graphics&#xff09;&#xff1a;GPU 天生本职工作 —— 画画面、渲染 3D、光栅化、纹理、着色、显示输出。GPU 算力&#xff08;Compute / GPGPU&#xff09;&#xff1a;利用 GPU 超多小核心 做通用并行计算 —— AI、科学计算、挖矿、渲染、仿…...

深度学习中的池化层:原理、实现与优化策略

1. 池化层的基本概念与作用 第一次听说"池化层"这个词时&#xff0c;我脑海中浮现的是游泳池的画面。但深度学习中的池化层可比游泳池有趣多了——它是卷积神经网络(CNN)中的关键组件&#xff0c;就像一位精明的数据压缩师。想象你正在看一张高清照片&#xff0c;当你…...

从‘电池’到‘胡萝卜’:聊聊构建YOLO生活垃圾数据集时遇到的坑与收获

从‘电池’到‘胡萝卜’&#xff1a;构建YOLO生活垃圾数据集的实战思考 去年夏天&#xff0c;我在自家小区做垃圾分类志愿者时&#xff0c;发现一个有趣现象&#xff1a;居民们对"1号电池属于有害垃圾"这类规则记得很牢&#xff0c;但面对"半个胡萝卜该扔哪个桶…...

手把手教你用Burp Suite搞定PortSwigger Labs的CSRF靶场(附12个Lab实战POC)

Burp Suite实战指南&#xff1a;12种CSRF漏洞攻防演练 在Web安全领域&#xff0c;CSRF&#xff08;跨站请求伪造&#xff09;始终是排名前五的高危漏洞类型。PortSwigger Labs作为全球知名的Web安全实战平台&#xff0c;其CSRF靶场设计了12个由浅入深的实验场景。本文将带你使用…...