关于TDL测试描述语言的设计草稿
TDL(Tests Description Language )
基于JSON的测试描述语言, 用于描述测试用例、测试套件、测试报告等相关实体及属性
设计初衷
- 为不同的程序语言(Python、Java、Golang等)提供一种通用的测试用例等对象的序列化参考格式
- 为基于文件系统的测试框架(Test Framework)到基于关系型数据库的测试平台(Test Platform)提供一种标准的中间格式
- 相对于Robot Framework及BDD的格式,使用更通用JSON格式,易于序列化和反序列化及平台支持和实现跨编程语言
参考格式
- Root Framework
- Httprunner
- Jenkins pipline
- BDD (Behave、Cucumber )
- QTAF (腾讯开源测试框架)
测试用例描述
- name: 用例名称(string格式)- 必填
- description: 用例描述(string格式)
- priority: 优先级(integer格式)
- tags: 用例标签列表(array格式)
- timeout: 超时时间,单位秒(interger / float格式)
- setups:测试准备操作(array of object格式)
- teardowns: 测试清理操作(array of object格式)
- steps: 测试步骤(array of object 格式)
- _id: 用例唯一ID(隐藏属性,计算生成)
- _path: 用例文件路径(可以单独一个文件)
对于基于关系行数据库的,_id字段也可以是一个数字(字符串形式),对于基于Mongodb等的,_id也可以时一个uuid,对于测试框架,_id可以是一个
包.模块.方法
的路径
测试步骤描述
- method: 引用的操作关键字,格式为
库.方法
- args: 支持number, string, array和object格式,object格式按关键字参数形式传给对应method,其他按位置参数形式传递(array拆成多个参数传递)
- store: 存储变量到上下文中(object格式)
- excepted: 步骤期望结果(array or object格式)
示例
示例1-接口自动化测试
{
"name": "test_api_demo",
"description": "test description",
"priority": 1,
"tags": ["http", "api-test"],
"timeout": 100,
"setups": [
{"method": "Http.Get", "args": {"url": "/get","params": {"a": 1, "b": 2, "c": 3}}}
],
"teardowns": [
{"method": "Http.Get", "args": {"url": "/get","params": {"a": 1, "b": 2, "c": 3}}}
],
"steps": [
{"method": "Http.Get", "args": {"url": "/get","params": {"a": 1, "b": 2, "c": 3}}},
{"method": "Http.Post", "args": {"url": "/post", "json": {"name": "Kevin"}}},
{"method": "Http.Get", "args": {"url": "/get", "params": {"a": 1, "b": 2, "c": 3}},
"store": {"url": "$.url"}, "excepted": [{"AssertEqual": ["$url", "/get"]}]
]
}
示例2-UI自动化测试
{
"name": "test_web_ui_demo",
"description": "test description",
"steps": [
{"method": "Page.Open", "args": ["https://www.baidu.com/"]},
{"method": "Page.InputTo", "args": ["id","kw", "helloworld"], "store": {"value1": "//[@id=\"kw\"]/@value"}},
{"method": "Page.Click", "args": ["id","su"]}
]
}
示例3-SSH操作
{
"name": "test_ssh_demo",
"description": "test description",
"steps": [
{"method": "SSH.Execute", "args": "echo hello"},
{"method": "SSH.GET", "args": ["/path/a.txt", "/local_path/a.txt"]}
]
}
示例4-MySQL操作
{
"name": "test_mysql_demo",
"description": "test description",
"steps": [
{"method": "MySQL.Query", "args": "SELECT * FROM `users`"},
{"method": "MySQL.Execute", "args": "INSERT INTO `users` (\"name\") VALUES(\"KEVIN\")"}
]
}
测试套件描述
- name: 测试套件名称(string格式)- 必填
- description:测试套件描述(string格式)
- priority: 套件下用例默认优先级(integer格式)
- tags: 套件下用例默认标签列表(array格式)
- timeout: 套件下用用例默认超时时间,单位秒(interger / float格式)
- setups:套件下用例默认测试准备操作-每个用例执行(array of object格式)
- teardowns: 套件下用例默认测试清理操作-每个用例执行一次(array of object格式)
- setups-suite:套件级测试准备操作(array of object格式)
- teardowns-suite: 套件级测试清理操作(array of object格式)
- tests: 测试用例列表,可以通过id引用,也可以直接描述完整的测试用例 (array of object格式)
- filter: 过滤器(object格式)
- _id: 套件唯一ID(隐藏属性,计算生成)
- _path: 套件文件路径
测试套件的两种形式
- 基于编写的
- 基于筛选或导入的
示例数据1-基于编写的
{
"name": "testsuite_01",
"description": "testsuite description",
"tags": ["ui-test"],
"priority": 1,
"tests": [
{
"name": "test_web_ui_demo",
"description": "test description",
"steps": [
{"method": "Page.Open", "args": ["https://www.baidu.com/"]},
{"method": "Page.InputTo", "args": ["id","kw", "helloworld"], "store": {"value1": "//[@id=\"kw\"]/@value"}},
{"method": "Page.Click", "args": ["id","su"]}
]
}
]
}
示例数据2-导入目录及过滤
{
"name": "testsuite_01",
"tests": [{"path": "./testcases"}],
"filter": {
"priorities": [],
"status": [],
"owner": [],
"include_tags": [],
"exclude_tags": [],
"exclude_names": []
},
}
示例数据3-逐个导入(用例列表)
{
"name": "testsuite_01",
"tests": [
{"path": "./testcases/function/test_a.json"},
{"path": "./testcases/function/test_c.json[A]"},
{"path": "./testcases/function/test_b.json[A,B,C]"},
],
}
一个.json可能包含多个用例(测试套件),可以通过[]
来筛选要导入的具体用例,不指定时导入套件所有用例
套件嵌套 # todo
示例数据3-基于ID导入
{
"name": "testsuite_01",
"tests": [
{"id": "testcases.function.test_a"},
{"id": "testcases.function.test_c.A"},
{"id": "testcases/=.function/test_b"}
],
}
基于编写的用例,套件中可以为下面的用例制定默认的priority、timeout、tags等属性,及setup、teardown方法
关于默认属性和属性优先级
对与基于编写的测试套件和测试用例都提供了priority、timeout、tags、setup、teardown等属性,优先级规则如下:
- priority、timeout:套件有-用例也有时,用例覆盖套件属性设置
- tags:套件有-用例有时,融合所有的标签
- setup、teardown:套件有-用例有事,融合操作,setup方法套件默认设置先执行,teardown套件默认设置后执行
测试报告描述
- title: 测试报告标题(string格式)- 必填
- description: 测试报告描述(string格式)
- summary:报告该要信息(object格式)
- details: 用例详细执行信息(array格式)
- _id: 报告唯一ID(隐藏属性,计算生成)
- _path: 报告文件路径
示例格式-待完善
{
"title": "test_report",
"summary": {
"start_at": "2015-02-03 12:00:00.000",
"end_at": "2015-02-03 12:01:00.00",
"total": 12
},
"details": [
{}
]
}
qtaf json report格式
{
"version": "1.0",
"summary": {
"tool": "QTA",
"title": "\u8c03\u8bd5\u6d4b\u8bd5",
"environment": {
"hostname": "SUPERHINHAN-MB1",
"os": "posix.uname_result(sysname='Darwin', nodename='SUPERHINHAN-MB1', release='22.4.0', version='Darwin Kernel Version 22.4.0: Mon Mar 6 21:00:17 PST 2023; root:xnu-8796.101.5~3/RELEASE_X86_64', machine='x86_64')",
"qtaf_version": "v5.6.3",
"python_version": "3.9.6[darwin]"
},
"start_time": "2023-07-13 18:35:22",
"testcase_total_run": 1,
"testcase_total_count": 1,
"testcase_passed": 1,
"succeed": true,
"end_time": "2023-07-13 18:35:22"
},
"logs": [],
"filtered_tests": [],
"load_errors": [],
"passed_tests": {
"TestA": {
"description": "\u6d4b\u8bd5\u7528\u4f8b\u63cf\u8ff0",
"owner": "superhin",
"priority": "High",
"status": "Ready",
"timeout": 10,
"failed_info": "",
"start_time": "2023-07-13 18:35:22",
"end_time": "2023-07-13 18:35:22",
"records": [
"TestA_20230713_183522394.json"
]
}
},
"failed_tests": {}
关于代码实现
- 关键字名称规范:大驼峰命名法(兼容Golang的Public函数)
内置关键字方法
- Log
内置断言方法
- AssertEqual
- AssertTrue
- AssertFalse
- AssertNone
- AssertNotNone
关于关键字库的实现
基于Python的实现示例
import tdl # todo
import requests
@tdl.library
class Http:
def Get(url, **kwargs):
pass
基于Java的实现示例
基于Golang的实现示例
关于自定义描述关键字
例如我们想使用verify代替excepted,用register代替store,用testcases代替tests
export TDL_KEY_EXCEPTED=verify
export TDL_KEY_STORE=register
export TDL_KEY_TESTS=testcases