5 个版本
0.1.5 | 2024 年 8 月 7 日 |
---|---|
0.1.4 | 2024 年 7 月 30 日 |
0.1.3 | 2024 年 7 月 29 日 |
0.1.2 | 2024 年 5 月 1 日 |
0.1.1 | 2024 年 4 月 30 日 |
#253 在 Web 编程
每月 426 次下载
71KB
1K SLoC
Testkit
Testkit 是由 APItoolkit 团队和杰出的社区 贡献者 开发的一款用于 API 手动测试和自动化测试任务的工具。Testkit 提供了一种简化的 YAML 语法来定义和执行 API 测试场景。
目录
为什么需要一个测试 DSL?
- 团队不应该因为想测试一个 Web 系统的 API 就被迫编写 JavaScript (Postman)、Groovy (Katalon) 或 Java (Rest-Assured)。
- 我们应该能够创建交互式构建器,生成这个底层的 DSL(领域特定语言)。因此,你甚至不需要在未来手动编写这个 DSL。
- 我们应该能够使用相同的脚本来进行单个测试和负载测试。
- 我们仍然能够在版本控制中持久化这些测试,并与同事协作。
- 受到 本地优先软件 原则的启发。
安装
要安装 testkit
,请按照以下选项之一操作(点击切换)
下载二进制文件
转到 发布页面,下载适用于您操作系统的最新版本的 testkit
二进制文件(Windows、macOS 或 Linux),然后继续安装。
二进制文件 | 描述 |
---|---|
testkit-发布-测试-i686-pc-windows-msvc.zip |
32 位 Windows (MSVC) |
testkit-发布-测试-x86_64-pc-windows-msvc.zip |
64 位 Windows (MSVC) |
testkit-发布-测试-x86_64-pc-windows-gnu.zip |
64 位 Windows (GNU) |
testkit-发布-测试-x86_64-apple-darwin.tar.gz |
64 位 macOS (Darwin) |
testkit-发布-测试-x86_64-unknown-linux-gnu.tar.gz |
64 位 Linux (GNU) |
下载后,提取 zip 文件并继续安装提取的文件。或者,如果您使用 macOS,可以使用 Homebrew 进行安装,如下所示
-
使用以下命令将
testkit
发布仓库添加为 Homebrew 公式源的切换brew tap apitoolkit/testkit
-
使用以下命令安装
testkit
brew install testkit
克隆仓库
请按照以下步骤在本地构建项目
-
确保您的计算机上已安装 Rust 编程语言和 Cargo 包管理器。
-
使用以下命令从 GitHub 克隆
testkit
仓库git clone https://github.com/testkit/testkit
-
使用以下命令打开克隆的目录
cd testkit
-
使用以下 Cargo 命令构建项目
cargo build --release
-
构建过程完成后,您将在
target/release
目录下找到testkit
可执行文件。 -
使用以下命令运行
testkit
CLI 工具testkit test --file ./test.tk.yaml
-
为了进一步测试,请确保将
./test.tk.yaml
替换为您 YAML 测试文件的路径。
[注意]
成功安装
testkit
后,运行testkit --help
命令以获取所有 CLI 命令和选项。
与其他测试库的比较
在深入了解 testkit
及其功能之前,让我们将其与其他测试库进行比较,以突出其优雅、简洁和简单。通过展示差异,您将看到 testkit
如何提供更流畅、更用户友好的 API 测试方法。为了说明这一点,我们将重写以下 Cypress 测试
Cypress ⤵️
describe('TODO API testing', () => {
let todoItem;
it('fetches Todo items - GET', () => {
cy.request('/todos/').as('todoRequest');
cy.get('@todoRequest').then((todos) => {
todoItem = todos.body[0]['_id'];
expect(todos.status).to.eq(200);
assert.isArray(todos.body, 'Todos Response is an array');
});
});
it('Deletes Todo items - DELETE', () => {
cy.request('DELETE', `/todos/${todoItem}`).as('todoRequest');
cy.get('@todoRequest').then((todos) => {
expect(todos.status).to.eq(200);
assert.isString(todos.body, 'todo deleted!');
});
});
it('Adds Todo item - POST', () => {
cy.request('POST', '/todos/', { task: 'run tests' }).as('todoRequest');
// Adds new Todo item by defining Todo name
cy.get('@todoRequest').then((todos) => {
expect(todos.status).to.eq(200);
cy.wrap(todos.body).should('deep.include', {
task: 'run tests',
completed: false,
});
});
});
});
Testkit ⤵️
---
- title: fetches TODO items - GET
GET: /todos/
asserts: # Asserts accepts a list of expressions, usually via JSONPaths to identify the items being referred to.
- ok: $.resp.status == 200 # Rely on an expressions library for parsing expressions
- array: $.resp.json
exports: # Values which should be accessible to future steps.
todoItem: $.resp.json[0]._id
- title: deletes TODO items - DELETE
DELETE: /todos/$.stages[0].todoItem # Relative syntax exists: $.stages[-1].todoItem, -1 means one stage before me
asserts:
- empty: $.resp.json.todos
- string: $.resp.json
- title: Adds Todo item - POST
POST: /todos/
json:
task: "run tests"
asserts:
- ok: $.resp.status == 200
- ok: $.resp.json.task == "run tests"
- ok: $.resp.json.completed == false
Testkit 提供了一种干净直观的语法,简化了定义和执行 API 测试场景的过程。
测试定义语法
Testkit 使用基于 YAML 的语法来定义测试场景。每个场景由多个阶段组成,其中每个阶段代表一个特定的 API 请求及其关联的断言。以下是定义 API 测试的 YAML 语法的示例
---
- title: fetches TODO items - GET
GET: /todos/
asserts:
- ok: $.resp.status == 200
- array: $.resp.json
exports:
todoItem: $.resp.json[0]._id
- title: deletes TODO items - DELETE
DELETE: /todos/$.stages[0].todoItem
asserts:
- empty: $.resp.json.todos
- string: $.resp.json
- title: Adds Todo item - POST
POST: /todos/
json:
task: "run tests"
asserts:
- ok: $.resp.status == 200
- ok: $.resp.json.task == "run tests"
- ok: $.resp.json.completed
在上面的示例中,YAML 测试文件定义了三个测试项:使用 GET 请求获取 TODO 项、使用 DELETE 请求删除特定的 TODO 项以及使用 POST 请求添加新的 TODO 项。YAML 文件由一系列测试场景组成。每个场景代表一个 API 请求,并包含以下字段
字段 | 描述 |
---|---|
title (必需) |
阶段的描述性名称。 |
request (必需) |
定义要发出的 API 请求,包括 HTTP 方法和 URL。 |
asserts (可选) |
可选。定义要执行以验证响应的断言。 |
exports (可选) |
可选。指定要从响应中捕获的值,供后续阶段使用。 |
请点击以下每个切换按钮,以了解更多关于每个字段的信息。
request
字段
在 testkit
中,request
字段定义要发出的 API 请求,并包含三个属性
method
(必需):此属性指定请求的 HTTP 方法,例如GET
、POST
、PUT
或DELETE
。method
属性的值是请求的 URL 路径。示例
# POST request
- title: Adds Todo item - POST
POST: /todos/
# GET request
- title: Fetches Todo items - GET
GET: /todos/
headers
(可选):此属性允许您在请求中包含 HTTP 头。头可以用于向服务器传递额外的信息,例如身份验证令牌或内容类型。示例
- title: Fetches Todo items - GET with headers
GET: /todos/
headers:
Authorization: Bearer <token>
Content-Type: application/json
Allowed-Methods:
- GET
- POST
json
(可选):此属性允许在必要时在请求中包含 JSON 格式的请求体数据。通过在request
字段中指定json
属性,您可以为 API 请求提供需要发送的格式化数据。示例
- title: Create User - POST
POST: /users/
json:
name: John Doe
age: 25
email: [email protected]
在上面的例子中,通过POST请求创建新用户。属性json
包含用户数据的JSON格式,包括诸如name
、age
和email
等属性。在request
字段中包含json
属性,您可以将结构化数据传递给API端点,从而便于在服务器上创建或更新资源。
在request
字段中的这些属性提供了在测试过程中对API请求的灵活性和控制。您可以指定HTTP方法,并在需要时包含头信息,以有效地与API端点交互。
asserts
字段
testkit
中的asserts
字段在定义要在API响应上执行的断言或验证中起着至关重要的作用。它允许您指定测试成功通过必须满足的条件。该字段接受一个键值对集合,其中键代表断言类型(可以将其视为变量),值定义了要评估的相应表达式或条件。您可以在asserts
字段中包含多个断言,以对API响应的不同方面执行各种验证,例如检查特定属性、验证某些数据的存在,或比较值。
以下是使用asserts
字段的示例
- title: Fetches Todo items - GET
GET: /todos/
asserts:
- ok: $.resp.status == 200
- array: $.resp.json
- ok: $.resp.json[0].task == "run tests"
注意:在
.json
中$.resp.json
告诉testkit
将响应转换为JSON格式。这允许您使用JSONPath表达式访问响应JSON的属性。
在上面的例子中,我们定义了三个断言
-
ok
:这个断言检查响应状态码是否等于200。表达式$.resp.status == 200
将被评估,如果它返回true
,则断言被认为是成功的。 -
array
:这个断言验证响应体是否为数组。表达式$.resp.json
将被评估,如果结果是数组,则断言被认为是成功的。 -
ok
:这个断言检查从API响应中检索到的第一个待办事项是否有一个任务名称等于"run tests"。表达式$.resp.json
将被评估,如果它返回true
,则断言被认为是成功的。
通过有效地利用asserts
字段,您可以确保API响应符合预期标准,从而对API的正确性和可靠性充满信心。您可以使用的所有可能的断言如下
断言 | 描述 |
---|---|
ok |
检查提供的表达式是否评估为true 。 |
empty |
检查一个值是否为空(例如,空数组、字符串或null)。 |
array |
检查一个值是否为数组。 |
string |
检查一个值是否为字符串。 |
number |
检查一个值是否为数字。 |
boolean |
检查一个值是否为布尔值。 |
null |
检查一个值是否为null。 |
exists |
检查一个值是否存在。 |
date |
检查一个值是否为有效的日期字符串。 |
这些断言提供了广泛的选择,用于验证API响应的不同方面,确保数据的正确性和完整性。您可以根据API测试场景的具体验证需求选择合适的断言。
exports
字段
testkit
中的 exports
字段允许您捕获并存储阶段的API响应值,以便在测试场景中未来参考。它提供了一种方便的方法来提取特定数据,并在测试的后续阶段使其可访问。
要使用 exports
字段,您定义键值对,其中键代表导出的名称(将其视为变量),而值定义用于从响应中提取所需数据的JSON路径或表达式。
以下是一个演示 exports
字段用法的示例
- title: Fetches Todo items - GET
GET: /todos/
exports:
todoItem: $.resp.json[0]._id
在上面的示例中,exports
字段捕获了API响应数组中第一个元素的 _id
属性的值。它将此值分配给 todoItem
导出。通过在 todoItem
导出中捕获 _id
值,您可以在测试场景的后续阶段访问它。这允许您使用提取的数据进行进一步的API请求、断言或任何其他必要的操作。
exports
字段使您能够在测试场景的不同阶段之间创建桥梁,提供在它们之间传递相关数据的方法。这在需要引用特定值或动态生成后续API请求的输入时尤其有用。使用 exports
字段,您可以增强API测试的灵活性和模块化,使它们更健壮且能适应不同场景。
什么是 JSONPath?
JSONPath 是一种强大的查询语言,旨在导航和从JSON文档中提取数据。它提供了一种简洁的语法,允许您指定到JSON结构中特定元素的路径,便于数据访问和操作。在 testkit
中,广泛使用JSONPath表达式来提取数据用于断言和导出。以下是一些示例来说明JSONPath的工作原理
$.user.name
:此表达式从JSON文档的顶层对象中检索用户名称。$.todos[0].task
:此表达式访问todos数组中第一个元素的task属性。$.todos[*].task.description
:此表达式检索todos数组中所有任务的description属性。
JSONPath表达式的语法包括几个关键组件
组件 | 描述 |
---|---|
括号表示法 | 通过在方括号内提供索引,访问数组中的元素([] )。 |
通配符 | 匹配当前级别的任何元素,允许检索该级别的所有元素(* )。 |
递归下降 | 允许在JSON结构中任何深度搜索元素,包括嵌套对象和数组(.. )。 |
过滤器 | 根据特定标准应用条件或过滤器以选择特定元素([?] )。 |
通过使用JSONPath表达式,您可以在JSON结构中精确地定位所需数据。这些表达式在testkit
中扮演着至关重要的角色,它有助于在测试过程中提取数据以进行断言和捕获导出。
[注意]
要了解更多关于JSONPaths的信息,请参阅官方文档。
引用值和动态输入用于后续 API 请求
testkit
中的exports
字段不仅允许您从API响应中捕获值,而且还提供了一个强大的机制来引用这些值,并在后续的API请求中动态生成输入。
通过使用exports
字段捕获相关数据,您可以将其存储为导出,并在测试场景的后续阶段轻松引用它。这种功能在您需要访问从响应中提取的特定值并在后续API请求中使用它们时尤其有用。
例如,假设您在第一阶段使用exports
字段从一个API响应中检索一个ID
- title: Fetch User - GET
GET: /users/1
exports:
userId: $.resp.body.id
为了在后续API请求中引用此userId
导出,您可以使用$.stages[n].<VAL>
语法
- title: Update User - PUT
PUT: /users/$.stages[0].userId
json:
name: 'John Doe'
在上面的示例中,使用语法$.stages[0].userId
访问了在第一阶段捕获的userId
。 testkit
理解它应该在执行期间用相应的值替换引用。
您还可以使用相对引用,如$.stages[-n]
,它引用当前阶段之前的第n个阶段的exports
。示例
- title: deletes TODO items - DELETE
DELETE: /todos/$.stages[-1].todoItem #-1 means one stage before me
asserts:
- string: $.resp.json.task
- ok: $.resp.json.id == $.stages[-1].todoItem
通过引用之前阶段捕获的特定值,您可以在不同的API请求之间建立依赖关系,并确保在整个测试场景中无缝地流动数据。这种灵活性允许您构建更全面、更现实的测试,模拟复杂的用户交互或工作流程。
日期断言
要在testkit
中进行日期断言,您需要提供日期字符串和日期格式,如下所示
- title: Get User Profile - GET
GET: /user/jon_doe
asserts:
- date: $.resp.json.createdAt %Y-%m-%d %H:%M:%S %Z
在上面的示例中,我们首先提供一个JSONPath到日期,然后是日期的格式。
更多关于日期格式的内容
Testkit使用chrono crate的格式化标记来表示日期的不同组成部分。以下是一些常用的格式化标记
标记 | 含义 | 示例 |
---|---|---|
%Y |
带有世纪的年份的十进制数字。 | 2023 |
%m |
作为零填充的十进制数字的月份。 | 07 |
%b 或%h |
月份的缩写名称。 | Jul |
%B |
月份的全称。 | July |
%d |
月份中的日,作为零填充的十进制数字。 | 03 |
%A |
星期的全称。 | Monday |
%a |
星期的缩写名称。 | Mon |
%H |
小时(00-23)。 | 14 |
%I |
小时(01-12)。 | 03 |
%M |
分钟(00-59)。 | 59 |
%S |
秒(00-59)。 | 45 |
%p |
12小时钟的AM/PM标识。 | PM |
%Z |
时区偏移或名称。 | UTC |
示例日期及其格式
以下是一些示例日期及其正确的格式
日期字符串 | 格式 |
---|---|
2023-07-26 | %Y-%m-%d |
2023-07-26 12:34:56 UTC | %Y-%m-%d%H:%M:%S%Z |
15 August, 1995, 03:45 PM UTC | %d%B, %Y, %I:%M%p%Z |
2022年12月5日 星期一 11:05:30 UTC | %a, %d%b%Y%H:%M:%S%Z |
2000年1月1日 - 00:00:00 UTC | %B%d, %Y- %H:%M:%S%Z |
1987/03/10 上午06:30 UTC | %Y/%m/%d%I:%M%p%Z |
在本表中,“日期字符串”列表示示例日期字符串,而“格式”列包含解析给定日期字符串的相应格式字符串。
使用环境变量
Testkit支持两种方式的环境变量(.env
文件和CLI配置)。这些方法允许用户配置和自定义他们的测试脚本,同时不暴露敏感数据,使无缝切换不同环境和场景变得更容易。
配置环境变量
使用.env
文件涉及到在测试脚本目录中创建一个名为.env
的文本文件,并为每个环境变量定义KEY=VALUE
对。在测试执行期间,testkit
自动从.env
文件中加载这些变量,如下所示
APIURL=https://api.example.com
EMAIL=[email protected]
PASSWORD=mysecretpassword
USERNAME=myusername
APIKEY=mysecretapikey
直接设置环境变量是通过命令行或测试环境完成的,如下所示
APIKEY=SECRETAPIKEY testkit test --file test.tk.yaml
利用环境变量
要在testkit
中利用环境变量,可以使用以下语法:$.env.<VAL>
,其中<VAL>
表示您想要使用的特定环境变量的名称。这允许您轻松引用和结合使用这些环境变量的值,在测试脚本中,从而提供更大的灵活性和适应性,而不需要将敏感信息或配置细节硬编码。以下是一个示例
- title: Register
POST: '$.env.APIURL/users'
headers:
Content-Type: application/json
X-Requested-With: XMLHttpRequest
json: '{"user":{"email":"$.env.EMAIL", "password":"$.env.PASSWORD", "username":"$.env.USERNAME"}}'
asserts:
- exists: $.resp.json.user
- exists: $.resp.json.user.email
- exists: $.resp.json.user.username
- exists: $.resp.json.user.bio
- exists: $.resp.json.user.image
- exists: $.resp.json.user.token
在这个例子中,testkit
向环境变量APIURL
中指定的API URL执行POST
请求。注册的用户信息来自环境变量EMAIL
、PASSWORD
和USERNAME
,允许轻松自定义和重用测试脚本,跨不同环境。
贡献和帮助
要为此项目做出贡献或请求社区和我们的团队的帮助,请执行以下任何一项
- 阅读我们的贡献指南。
- 加入我们的社区Discord服务器。
- 在此存储库中创建一个新问题。
许可协议
此存储库在MIT许可下发布。
依赖项
~24–38MB
~559K SLoC