OperationSequence DSL 2.1 语法规范
概述
OperationSequence (简称 OS) DSL 2.1 是一个基于 Read/Write/Ensure 序列的声明式操作与验证 DSL。它将所有操作抽象为三种核心动作:
- read: 读取数据(对应 HTTP GET / SQL SELECT / S3 SELECT 等)
- write: 写入或变更数据(对应 HTTP POST/PUT/PATCH/DELETE / SQL INSERT/UPDATE/DELETE 等)
- ensure: 断言数据符合预期,失败则中止
在此抽象之上,2.1 版本增强了 JSON 数据处理能力,支持原生 JSON 字面量和 Python 风格的三引号字符串,使脚本对初级测试人员和 AI 生成场景都更加友好。
采用两阶段执行模型:
- declare-block: 声明阶段,加载配置、声明服务和定义变量
- action-block: 执行阶段,按 read/write/ensure 序列执行具体操作
一、Declare-Block(声明块)
声明块位于脚本开头,负责配置加载、服务声明和变量定义。
1.1 配置文件加载
os
config <config_file_path>
说明:
- 加载外部配置文件(JSON/YAML 格式)
- 可多次加载,后加载的配置会覆盖之前的同名配置
- 配置文件必须存在,否则报错终止
示例:
os
config ./config/dev.json
config ./config/secrets.json
1.2 数据服务声明
os
data-service <service_name>
说明:
- 声明要使用的数据服务
<service_name>必须在已加载的配置文件中定义- 未定义的服务会导致执行终止
示例:
os
data-service mysql_db
data-service sqlite_cache
data-service postgres_main
1.3 HTTP 服务声明
os
http-service <service_name>
说明:
- 声明要使用的 HTTP 服务
<service_name>必须在已加载的配置文件中定义- 未定义的服务会导致执行终止
示例:
os
http-service user_api
http-service product_api
1.4 变量声明
os
var <variable_name> = <value>
说明:
- 声明具名变量并赋值
- 变量可使用字面值、内置函数、环境变量或原生 JSON
- 变量在后续操作中通过
@{variable_name}引用
示例:
os
var user_id = "U001"
var user_name = random_name()
var password = random_password()
var age = random_int(18, 65)
var amount = random_float(10.0, 1000.0)
// v2.1 新增:原生 JSON 字面量
var profile = {"level":"gold","score":8800}
// v2.1 新增:多行 JSON
var product = {
"name": "机械键盘",
"price": 599.00,
"tags": ["电子", "外设", "热卖"]
}
// v2.1 新增:三引号字符串
var longText = """多行文本内容"""
1.5 原生 JSON 字面量支持(v2.1 新增)
语法:
os
var <name> = {<json_object>}
var <name> = [<json_array>]
说明:
- 变量赋值时支持直接书写 JSON 对象/数组,无需字符串包裹和转义
- 以
{或[开头的赋值内容自动解析为 JSON - JSON 字面量可跨多行书写,缩进由解析器自动忽略
示例:
os
// 单行 JSON
var order = {"productId":"P001","quantity":2}
// 多行 JSON
var order = {
"productId": "P001",
"quantity": 2,
"shipping": {
"address": "北京市朝阳区",
"method": "express"
}
}
1.6 三引号字符串(v2.1 新增)
语法:
os
var <name> = '''<content>'''
var <name> = """<content>"""
说明:
- 支持多行字符串,保留原始格式
- 单引号
'''和双引号"""等价 - 常用于定义超长文本或 JSON 字符串
示例:
os
var jsonData = '''{
"productId": "P001",
"quantity": 2
}'''
var article = """欢迎来到 OperationSequence DSL。
这是一个专注于 Read/Write/Ensure 序列的声明式测试语言。
无论底层是 HTTP、数据库还是对象存储,都可以用统一的原语描述。"""
1.7 JSON 内变量嵌入(v2.1 新增)
语法:
os
var product_id = "P001"
var order = {
"productId": @{product_id}
}
说明:
- 在 JSON 字面量中,
@{var_name}会被自动替换为对应变量值 - 字符串类型变量自动添加引号
1.8 内置随机函数
random_int(min, max)
生成指定范围内的随机整数
os
var user_age = random_int(18, 65)
var order_no = random_int(1000, 9999)
random_float(min, max)
生成指定范围内的随机浮点数
os
var price = random_float(0.01, 99.99)
var amount = random_float(10.0, 1000.0)
random_name()
生成随机用户名
os
var user_name = random_name()
random_password()
生成随机密码
os
var password = random_password()
random_string(length)
生成指定长度的随机字符串
os
var session_id = random_string(32)
var token = random_string(16)
二、Action-Block(执行块)
执行块包含具体的操作指令。所有指令均可归类为 read / write / ensure 三种核心动作。
指令统一格式:SERVICE VERB [TARGET] BODY [HEADER]
2.1 数据操作(CRUD)
所有 CRUD 动词本质都是 read / write 的具体形式:
insert/update/delete→ writeselect/query→ read
INSERT - 写入数据
os
<service> insert <table> <json_body>
示例:
os
mysql_db insert products {"product_id": "@{product_id}", "name": "机械键盘", "price": 599.00}
SELECT - 读取数据
os
<service> select <table> [where <condition>]
示例:
os
mysql_db select products where product_id = '@{product_id}'
sqlite_cache select sessions
UPDATE - 更新数据
os
<service> update <table> <json_body> [where <condition>]
示例:
os
mysql_db update products {"price": 499.00} where product_id = '@{product_id}'
DELETE - 删除数据
os
<service> delete <table> [where <condition>]
示例:
os
mysql_db delete products where product_id = '@{product_id}'
SQL 直接查询
os
<service> query <sql_statement>
示例:
os
mysql_db query SELECT COUNT(*) FROM products WHERE status = 'on_sale'
2.2 HTTP 请求
HTTP 的 get/post/put/delete/patch 同样可归为 read / write:
get→ readpost/put/patch/delete→ write
os
<service> <http_method> <path> [json_body] [headers]
HTTP 方法: GET, POST, PUT, DELETE, PATCH
示例:
os
user_api get /users/@{user_id}
product_api post /orders {"productId": "@{product_id}", "quantity": 2}
user_api put /users/@{user_id} {"nickname": "alex_updated"} headers {"Authorization": "Bearer @{token}"}
2.3 结果捕获
os
capture <expression> as <variable_name>
说明: 将执行结果保存到变量,供后续使用
示例:
os
user_api get /users/@{user_id}
capture result.user_name as api_username
capture result.status as user_status
2.4 断言校验(Ensure)
os
ensure <expression>
说明: 验证表达式是否为真,失败则终止执行。这是 OperationSequence 的核心 ------ 通过断言保证 read/write 操作后的系统状态符合预期。
示例:
os
user_api get /users/@{user_id}
ensure result.user_name == '@{user_name}'
ensure result.status == 'active'
ensure result.level == 'gold'
ensure $status == 200
2.5 变量引用
使用 @{variable_name} 引用已声明或已捕获的变量
示例:
os
var uid = random_string(8)
user_api get /users/@{uid}
capture result.user_id as captured_uid
mysql_db select orders where user_id = '@{captured_uid}'
ensure result[0].status == 'completed'
2.6 输出打印
os
echo <text>
说明: 输出文本信息,用于调试和日志
示例:
os
echo "Starting user verification..."
user_api get /users/@{user_id}
echo "User: @{user_name} verified successfully"
2.7 注释
os
// 单行注释
/* 多行注释 */
三、配置文件格式
配置文件采用 JSON 格式,包含数据源和 HTTP 服务定义。
3.1 完整配置示例
json
{
"data-services": {
"mysql_db": {
"type": "mysql",
"host": "127.0.0.1",
"port": 3306,
"database": "test_db",
"username": "${MYSQL_USER}",
"password": "${MYSQL_PASS}"
},
"sqlite_cache": {
"type": "sqlite",
"path": "./data/cache.db"
},
"postgres_main": {
"type": "postgresql",
"host": "127.0.0.1",
"port": 5432,
"database": "app_db",
"username": "${PG_USER}",
"password": "${PG_PASS}"
}
},
"http-services": {
"user_api": {
"base_url": "http://127.0.0.1:80/v1",
"headers": {
"Content-Type": "application/json",
"X-App-Key": "${APP_KEY}"
},
"timeout": 30000
},
"product_api": {
"base_url": "http://127.0.0.1:80",
"headers": {
"Authorization": "Bearer ${APP_TOKEN}"
}
}
}
}
3.2 数据源类型
| 类型 | 说明 | 必需字段 |
|---|---|---|
| mysql | MySQL 数据库 | host, port, database, username, password |
| sqlite | SQLite 文件数据库 | path |
| postgresql | PostgreSQL 数据库 | host, port, database, username, password |
| sqlserver | SQL Server 数据库 | host, port, database, username, password |
| csv | CSV 文件 | path |
3.3 环境变量引用
配置文件中可使用 ${ENV_VAR} 格式引用环境变量。
四、完整脚本示例
4.1 电商商品与订单示例
os
// 加载配置文件
config ./config/config.json
// 声明要使用的服务
data-service mysql_db
http-service product_api
http-service order_api
// 声明测试变量(使用随机函数生成测试数据)
var product_id = random_string(8)
var product_name = "机械键盘 @{product_id}"
var price = random_float(300.0, 900.0)
var stock = random_int(100, 1000)
var quantity = random_int(1, 5)
// === Read/Write/Ensure 序列:商品上架 ===
echo "=== 步骤 1: 写入商品数据 ==="
// Write: 直接写入数据库,构造前置状态
mysql_db insert products {
"product_id": "@{product_id}",
"name": "@{product_name}",
"price": @{price},
"stock": @{stock},
"status": "on_sale"
}
// Read: 通过 HTTP 读取,验证写入
product_api get /products/@{product_id}
capture result as fetched_product
// Ensure: 校验字段正确
ensure fetched_product.name == '@{product_name}'
ensure fetched_product.price == @{price}
ensure fetched_product.stock == @{stock}
ensure fetched_product.status == 'on_sale'
echo "商品创建并校验通过: @{product_name}"
// === Read/Write/Ensure 序列:创建订单 ===
echo "=== 步骤 2: 写入订单 ==="
// Write: 调用 HTTP 接口下单
order_api post /orders {
"productId": "@{product_id}",
"quantity": @{quantity}
}
capture result.orderId as order_id
ensure $status == 201
// Read: 查询订单状态
order_api get /orders/@{order_id}
ensure result.status == 'paid'
ensure result.totalAmount == @{price * quantity}
// Ensure: 校验数据库中的持久化事实
mysql_db query SELECT stock FROM products WHERE product_id = '@{product_id}'
capture result[0].stock as remaining_stock
ensure remaining_stock == @{stock - quantity}
echo "订单 @{order_id} 创建成功,库存更新为: @{remaining_stock}"
// === Read/Write/Ensure 序列:下架商品 ===
echo "=== 步骤 3: 更新商品状态 ==="
// Write: 数据库写入新状态
mysql_db update products {"status": "off_shelf"} where product_id = '@{product_id}'
// Read + Ensure: HTTP 读取并断言下架
product_api get /products/@{product_id}
ensure result.status == 'off_shelf'
echo "=== 所有 Read/Write/Ensure 序列通过 ==="
4.2 博客文章发布示例(v2.1 增强特性)
os
// 声明服务
data-service mysql_db
http-service blog_api
// 变量
var author_id = random_string(6)
var title = "OperationSequence DSL 入门指南"
var tags = ["技术", "测试", "DSL"]
// v2.1 原生 JSON + 变量嵌入
var article = {
"title": "@{title}",
"authorId": "@{author_id}",
"tags": @{tags},
"published": true
}
// Write: HTTP 发布文章
blog_api post /articles @{article}
capture result.articleId as article_id
ensure $status == 201
echo "文章已发布: @{article_id}"
// v2.1 三引号字符串 - 定义评论内容
var comment = '''这篇文章讲得很清楚,
Read/Write/Ensure 的抽象让所有协议统一了。
期待更多示例!'''
blog_api post /articles/@{article_id}/comments {"content": "@{comment}", "author": "alex"}
ensure $status == 200
// Read + Ensure: 读取文章评论数
blog_api get /articles/@{article_id}/comments
ensure result.total >= 1
// Write + Ensure: 直接更新数据库,模拟管理员置顶
mysql_db update articles {"is_top": 1} where article_id = '@{article_id}'
mysql_db select articles where article_id = '@{article_id}'
ensure result[0].is_top == 1
echo "文章发布与置顶流程验证通过"
五、执行流程
- 解析阶段: 读取脚本,识别 declare-block 和 action-block
- 配置加载: 按顺序加载所有 config 文件
- 变量解析: 解析 var 声明,执行内置函数生成变量值,支持原生 JSON 和三引号字符串
- 服务验证: 检查声明的服务是否在配置中存在
- 执行阶段: 按顺序执行 action-block 中的指令(本质是 read/write 序列)
- 断言校验: 每个 ensure 指令是 read/write 序列的终点,校验数据符合预期,失败则终止
六、内置函数列表
| 函数 | 参数 | 返回值 | 示例 |
|---|---|---|---|
| random_int | (min, max) | 随机整数 | var age = random_int(18, 65) |
| random_float | (min, max) | 随机浮点数 | var price = random_float(1.0, 99.99) |
| random_name | (prefix) | 随机用户名 | var name = random_name() |
| random_password | () | 随机密码 | var pwd = random_password() |
| random_string | (prefix,length=10) | 指定长度随机字符串 | var sid = random_string(32) |
七、核心理念
OperationSequence DSL 将所有操作统一为 Read / Write / Ensure 三种动作的有序序列:
- Read:从系统中获取事实(HTTP GET / SQL SELECT)
- Write:向系统写入或变更事实(HTTP POST/PUT/DELETE / SQL INSERT/UPDATE/DELETE)
- Ensure:基于事实做出判定,是 Read/Write 序列的闭环
无论底层是 HTTP 接口、关系数据库还是对象存储,测试脚本始终围绕"写入 → 读取 → 断言"的模式组织。这种抽象使得:
- 脚本结构对初级测试人员一目了然
- AI 可以稳定地生成符合该结构的脚本
- 审查者可以聚焦于事实判断,而非语法细节