SurrealDB 的 SurrealQL 语言测试套件:从测试格式到多后端执行引擎的完整指南
【免费下载链接】surrealdbA scalable, distributed, collaborative, document-graph database, for the realtime web项目地址: https://gitcode.com/GitHub_Trending/su/surrealdb
本指南以仓库中的 language-tests/README.md 为骨架,系统讲解 SurrealDB 的 SurrealQL 语言测试体系:它由一组用 SurrealQL 编写、以特殊注释内嵌 TOML 配置的.surql测试文件,以及一个负责加载、调度、执行并校验结果的surrealql-test命令行工具组成。读完本文,你将掌握语言测试的编写格式、[test]与[env]两大配置表的全部字段语义、结果校验的三种机制(精确值、跳过字段、匹配表达式),并理解工具如何跨内存、RocksDB、SurrealKV、TiKV 四种存储后端与新旧两代执行器运行测试。
一、什么是 SurrealQL Language Tests
SurrealDB 的仓库根目录下有一个独立的工作区 language-tests/,其中包含两部分:
- 测试用例集:位于 language-tests/tests/,是一批可被标准 SurrealQL 解析器正常解析的
.surql文件,按主题组织成access、language、parsing、self_tests、upgrade、api等目录。 - CLI 工具:即
surrealql-test二进制,定义在 language-tests/Cargo.toml(name = "surrealql-test",版本0.1.0),它负责实际运行测试文件并校验输出。
从源码结构看,该工具内部按职责拆分为多个模块(见 language-tests/src/main.rs):cli(命令行解析)、cmd(子命令实现)、runner(并发调度)、tests(用例加载、配置解析、报告与结果比较)、format(输出格式化)、util(目录遍历等通用逻辑)。入口main基于clap解析出三个子命令并分发:
test(别名run):运行语言测试;upgrade:运行升级测试(仅在启用upgradefeature 时实现,否则直接报错,见 language-tests/src/main.rs);list:列出测试用例。
二、快速上手:运行测试套件
在language-tests目录内,用一条命令即可跑完全部测试:
cargo run run这里的第二个run是传给工具本身的子命令(test的别名)。工具默认以./tests作为测试根目录,加载其中所有.surql文件并逐个执行、比对预期结果。该默认路径与 language-tests/src/cli.rs 中--path参数的default_value("./tests")一致。
常用命令行参数
| 参数 | 作用 | 默认值 |
|---|---|---|
[filter] | 路径过滤,只运行路径中包含该词条的测试 | 无(运行全部) |
--path <PATH> | 测试目录路径 | ./tests |
-j, --jobs <JOBS> | 并行运行的测试数 | 可用并行度 |
--results <MODE> | 结果处理模式:default/accept/overwrite | default |
--backend <BACKEND> | 存储后端:memory(别名mem) /rocksdb/surrealkv/tikv | mem |
--no-wip | 跳过标记为 WIP 的测试 | 不跳过 |
--no-results | 跳过已定义预期结果的测试(新增测试时有用) | 不跳过 |
--color <COLOR> | 输出着色:always/never/auto | auto |
以上参数在 language-tests/src/cli.rs 的test子命令定义中均有对应实现。其中--results支持三种模式(language-tests/src/cli.rs):
default:不修改任何测试文件;accept:为未指定预期结果的测试自动写入实际结果,适合快速为新增测试生成期望输出;overwrite:覆盖未指定结果以及校验失败的测试的预期结果,应谨慎使用,且必须先人工确认新结果确实是合法的。
路径过滤器
cargo run run foo会只运行路径中包含foo的测试。因为过滤器匹配的是测试文件的相对路径(见 language-tests/src/cmd/run/mod.rs,实际执行origin.path.contains(filter)),所以可以精确到单个文件(如cargo run run multi_line)或某一类目录(如cargo run run statements/select),非常适合调试手头正在编写的测试。
三、存储后端与 Cargo features
--backend参数决定测试跑在哪种存储引擎上,其枚举与别名定义在 language-tests/src/cli.rs:
| 后端 | CLI 值 | 说明 | 所需 feature |
|---|---|---|---|
| 内存 | mem/memory | 内存存储引擎,测试最快,默认选择 | 默认启用(kv-mem) |
| RocksDB | rocksdb | RocksDB 嵌入式存储引擎 | backend-rocksdb |
| SurrealKV | surrealkv | SurrealKV 基于文件的存储引擎 | backend-surrealkv |
| TiKV | tikv | TiKV 分布式存储引擎 | backend-tikv,且需要正在运行的 TiKV 集群 |
对应 feature 在 language-tests/Cargo.toml 中定义,均透传到surrealdb-core:backend-rocksdb = ["surrealdb-core/kv-rocksdb"]、backend-surrealkv = ["surrealdb-core/kv-surrealkv"]、backend-tikv = ["surrealdb-core/kv-tikv"]。而surrealdb-core依赖固定启用了kv-mem(见 language-tests/Cargo.toml),因此内存后端始终可用。
使用非默认后端时需要同时启用对应 feature:
# 使用 RocksDB 后端运行测试 cargo run --features backend-rocksdb run --backend rocksdb # 使用 SurrealKV 后端运行测试 cargo run --features backend-surrealkv run --backend surrealkv # 使用 TiKV 后端运行测试(需要本机 127.0.0.1:2379 有可用的 TiKV 集群) cargo run --features backend-tikv run --backend tikv如果未启用对应 feature 却指定了该后端,工具会直接报错退出(见 language-tests/src/cmd/run/mod.rs,例如RocksDb backend feature is not enabled)。
另外还有upgradefeature:upgrade = ["backend-surrealkv", "tokio-tungstenite", "revision"](见 language-tests/Cargo.toml),用于编译升级测试子命令,它会通过 WebSocket 与旧版 SurrealDB 服务器通信。
四、测试文件格式:SurrealQL + 注释内嵌 TOML
任何能被标准 SurrealQL 解析器解析的.surql文件都可以作为语言测试,但要让测试真正有用,必须通过**测试注释(test comment)**声明配置。测试注释有两种写法:
- 单行形式:以
//!开头的注释; - 多行形式:
/** ... */(注意是两个星号,区别于普通块注释/* */)。
工具运行测试时,会把文件中所有测试注释拼接起来,整体按 TOML 解析。该解析逻辑实现在 language-tests/src/tests/case/config.rs:源码扫描器遇到/**即认为进入配置段,直到遇到*/结束;若文件包含多个配置段会直接报错(Test case contains multiple config sections),配置未闭合也会报错。解析出的 TOML 随后反序列化为TestConfig结构(见 language-tests/src/tests/schema/mod.rs)。
下面是一个完整的最小测试文件(来自 language-tests/tests/self_tests/multi_line.surql):
/** [env] clean = false namespace = "test" database = "test" timeout = 1000 context-timeout = 1000 sequential = false imports = [] [test] reason = "Unsure multi line comments are properly parsed as toml." run = true [[test.results]] value = "'foo'" [[test.results]] error = true */ RETURN "foo"; 1 + "1";这个例子同时演示了测试注释的典型用法:[env]声明运行环境,[test]声明测试元信息与预期结果,而/** */注释之后才是真正被测的 SurrealQL 语句。
五、[test]配置表:测试自身的元信息
[test]表描述测试本身的信息,其字段定义见 language-tests/src/tests/schema/mod.rs。所有键均可选,未指定时使用默认值。
reason与issue
reason:字符串,说明该测试存在的原因;issue:该测试关联的 GitHub issue 编号。
二者主要是文档用途,不过有一个联动行为:当测试标记为wip且指定了issue时,若测试通过,CLI 会提示可以关闭该 issue。两者默认均为空。
run
有些文件被纳入测试套件只是为了作为其他测试的导入文件,并不关心它自身的输出。此时将run设为false即可禁止其作为独立测试运行。默认为true。工具在构建运行集时会用test.run作为过滤条件(见 language-tests/src/cmd/run/mod.rs)。
wip
对于已知缺陷或尚未完成的功能,可以先把测试标记为wip = true:
- 测试结果的错误会被降级为警告,从而不会导致整个测试运行失败;
- 使用
--results accept/--results overwrite时,WIP 测试的预期结果不会被自动更新。
默认为false。
version
该测试对运行数据存储版本的语义化版本要求,格式与Cargo.toml中 Rust 依赖版本约束一致(如"^2.0.0"、">=1.5, <3")。若当前运行的 surrealdb 版本不满足要求,测试将被跳过。默认值为"*"(不限制)。
需要注意的是,导入该文件时此版本仍会与导入方数据存储的版本比对,不匹配则整个测试不会运行。
importing-version
针对测试导入的版本要求。若导入方版本不满足,整个测试不会运行。对普通测试意义不大(因为导入方与运行方通常是同一数据存储),它主要用于升级测试——升级场景中升级后的数据存储版本可能与运行测试的数据存储版本不同。默认值为"*"。
[test.results]:预期结果
[test.results]声明测试的预期输出。CLI 会对每个未声明该表的测试给出警告。该表既可以是普通表,也可以是表数组([[test.results]])。
解析错误测试
当测试预期产生解析错误时使用parsing-error键:
[test.results] parsing-error = "foo"以上配置要求测试返回文本为foo的解析错误。由于一个测试文件只会被解析一次、最多产生一个解析错误,因此解析错误测试只允许声明一个结果。真实仓库中的示例(来自 language-tests/tests/language/functions/type_record.surql 一类的用例)如下:
/** [test] [test.results] parsing-error = """ Invalid function/constant path, did you maybe mean `type::record` --> [16:1] | 16 | type::thing("person", "one"); | ^^^^^^^^^^^ """ */ type::thing("person", "one"); // 注意:同一文件内不能再追加其他断言,必须另起文件 // string::slayce();parsing-error还允许布尔值:
[test.results] parsing-error = truetrue只要求存在解析错误,false只要求不存在解析错误,二者均不校验错误文本。
普通查询结果测试
若测试不预期解析错误,通常应声明各条语句的实际输出。一条 SurrealQL 查询可由多条语句组成,每条语句产生零个或一个结果。测试允许指定结果的数量与值:
[[test.results]] value = "[{ id: foo:bar, name: 'bar' }]" [[test.results]] error = "Some error is happening here" [[test.results]] error = false [[test.results]] error = true上面的配置声明测试应返回 4 个结果:
- 第一个必须是字符串
value所描述的 SurrealQL 值(TOML 字符串内书写的是 SurrealQL 表达式); - 第二个必须是一个错误,且错误文本与给定字符串完全一致;
- 第三个只需不是错误,不检查具体值;
- 第四个只需是错误,不检查错误文本。
只要实际结果的数量或值与声明不一致(多一个、少一个、不相等),测试即失败。从源码看,结果表在反序列化时按内容自动区分形态(见 language-tests/src/tests/schema/mod.rs):包含match键的走Match分支、包含value键的走Value分支、包含error键的走Error分支。value字段由 SurrealQL 解析器以特定ParserSettings解析为SurrealConfigValue(见 language-tests/src/tests/schema/mod.rs)。
粗略相等(Rough equality)
有些 SurrealQL 值本质上是非确定性的,比如泛型 record-id 的键通常是随机的 ULID,会导致固定输出比较不稳定。除使用匹配表达式外,对常见场景可以忽略值的某些部分:
| 字段 | 作用 |
|---|---|
skip-datetime | 跳过 datetime 值相等性比较 |
skip-record-id-key | 忽略 record-id 的键(只比较表名) |
skip-uuid | 跳过 uuid 值比较 |
这些字段的解析定义在 language-tests/src/tests/schema/mod.rs 的ValueTestResult中(此外还支持skip-api-request-id、float-roughly-eq、decimal-roughly-eq)。例如:
[[test.results]] value = "foo:bar" skip-record-id-key = true会匹配任意表名为foo的 record-id,而忽略其键部分。
匹配表达式(Matching expressions)
当精确匹配不可行时,可以退而求其次,用一段 SurrealQL 表达式来校验输出。在[[test.results]]上设置match字段即可;该表达式必须返回布尔值true表示校验通过。表达式中可通过两个参数访问输出:
$result:当前语句的实际输出值;$error:当前语句出错时的错误文本(仅当输出为错误时定义)。
通常一个匹配表达式只应匹配值或错误之一,此时可在同一结果上设置error字段为true或false加以限定。官方文档中的示例:
# 语句输出要么是字符串 foo,要么是错误 'An error occurred: foo' [[test.results]] match = "$result == 'foo' || $error == 'An error occurred: foo'" # 用正则匹配错误,因为错误部分内容非确定 [[test.results]] match = "$error = /Found record: `thing:.*` which is not a relation, but expected a NORMAL/" error = true # 校验结果字段是否符合正则(注意对 TOML 字符串中反斜杠的转义) [[test.results]] match = """ $result.users.test = /DEFINE USER test ON ROOT PASSHASH '\\$argon2id\\$.*' ROLES VIEWER DURATION FOR TOKEN 1h, FOR SESSION NONE/ """ error = false从 language-tests/src/tests/schema/mod.rs 可以看到MatchTestResult同时携带match与可选的error字段;其反序列化注释还特别强调:Match变体必须排在Error之前,否则当match指定了是否期待错误时会被错误地解析成错误分支。
六、[env]配置表:测试运行环境
[env]表描述测试的运行环境,字段定义见 language-tests/src/tests/schema/mod.rs。同样所有键均可选、均有默认值。
clean
为了提速,CLI 通常会尽量在测试间复用数据库:一个测试跑完后删除其使用的 namespace 与 database,下一个测试再在干净环境中运行。但如果某个测试可能在被删库后仍影响后续状态,就需要clean = true,让它在全新创建的数据库中运行,并在测试结束后销毁。默认为false。
sequential
CLI 会尽可能并行运行测试,如果并行会造成干扰、或该测试占用大量线程,可设sequential = true保证没有其他测试同时运行。默认为false。调度器的实现位于 language-tests/src/runner/mod.rs:并行任务通过Semaphore获取 1 个许可(spawn),而spawn_sequential会一次获取全部许可(acquire_many(max_jobs)),从而独占整个调度器,实现“顺序运行”。
namespace与database
设置测试运行的 namespace 与数据库名称,取值可以是字符串或布尔值:
- 字符串:使用该字符串作为名称;
true:使用默认名"test";false:测试不在 namespace / 数据库内运行。
两者默认值均为true(即默认 namespace 与 database 名为"test")。源码中默认常量ENV_DEFAULT_NAMESPACE与ENV_DEFAULT_DATABASE均为"test"(见 language-tests/src/tests/schema/mod.rs)。在配置解析层,该字段由BoolOr<T>枚举支持(见 language-tests/src/tests/schema/mod.rs),into_value逻辑正是:false→ 无、true→ 默认值、具体值 → 该值。
imports
字符串数组,指定在运行测试之前要先执行的文件。路径规则:
- 以
./或../开头:相对于当前测试文件所在目录解析; - 其他路径:相对于测试根目录解析。
路径解析逻辑在 language-tests/src/tests/case/mod.rs 的find_import中实现。每个导入文件都会在具备完整能力的数据库、以及给定的 namespace 和 database 中执行;只有全部导入文件执行完成后才开始测试。导入时会校验被导入文件的[test.version]是否匹配当前导入方数据存储的版本,不匹配则整个测试不运行。
典型用途包括:运行查询前导入数据集、导入工具函数、或先以 root 权限建立数据库再运行权限相关测试。默认值为[]。
backend
指定该测试应在哪些存储后端上运行,值为后端标识字符串数组:
"mem":内存存储引擎;"rocksdb":RocksDB 嵌入式存储引擎;"surrealkv":SurrealKV 文件存储引擎;"tikv":TiKV 分布式存储引擎。
行为规则:
- 数组为空(默认):在所有后端上运行;
- 数组非空:仅当通过
--backend选中的后端位于该列表中时才运行; - 完全不存在
[env]段:在所有后端上运行。
# 只在 RocksDB 上运行 [env] backend = ["rocksdb"] # 在内存与 RocksDB 上运行 [env] backend = ["mem", "rocksdb"] # 在所有后端上运行(空数组) [env] backend = [] # 在所有后端上运行(未声明 backend 字段) [env] namespace = "test"该功能对后端特有行为尤其有用,例如ALTER TABLE COMPACT语句在 RocksDB 上成功、在内存后端上返回错误。工具运行时将env.backend作为过滤条件(见 language-tests/src/cmd/run/mod.rs):列表为空或包含当前后端才运行。默认[]。
versioned
指定测试是否需要数据存储启用 MVCC 版本控制。设为true时,数据存储将以支持版本的方式创建,从而可以使用带VERSION子句的时间旅行查询。由于这类测试需要不同的数据存储配置,versioned = true的测试总是获得全新的数据存储,无法复用共享的数据存储池。默认为false。
# 需要版本化,且在内存与 SurrealKV 后端运行 [env] backend = ["mem", "surrealkv"] versioned = true # 在所有支持的启用版本化的后端运行 [env] versioned = truetimeout与后端专属覆盖
timeout以毫秒为单位限制整个测试从开始到结束的执行时间,超时视为错误并使测试运行失败。也可设为false完全禁用超时,或true使用默认值 5 秒。默认值为5000(5 秒)。
针对特定后端可覆盖基础超时:
| 键 | 作用 |
|---|---|
timeout-tikv | TiKV 后端超时(网络延迟通常需要更大值) |
timeout-rocksdb | RocksDB 后端超时(磁盘 I/O 可能稍慢) |
timeout-surrealkv | SurrealKV 后端超时 |
[env] timeout = 5000 # 内存后端超时 timeout-tikv = 10000 # TiKV 需要 2 倍时间(网络延迟) timeout-rocksdb = 6000 # RocksDB 因磁盘 I/O 可能需要略多时间context_timeout与后端专属覆盖
context_timeout以毫秒为单位限制数据存储上下文内单条查询的执行时间,超时即终止该查询。同样可设为false禁用或true使用默认 5 秒,默认5000。它也有对应的后端覆盖键:context-timeout-tikv、context-timeout-rocksdb、context-timeout-surrealkv。
[env] context-timeout = 5000 # 默认查询上下文超时 context-timeout-tikv = 10000 # TiKV 查询可能耗时更长注意两者的区别:
timeout:控制整个测试端到端的执行时间;context_timeout:控制测试内单条查询的执行时间。
signin与signup
指定如何登录数据存储,字段与signin/signupRPC 方法的入参类似:
[env] signin = """{ ns: "test", user: "ns_user", pass: "pass", }"""以上配置表示登录 namespacetest,用户名为ns_user,密码为pass。
时序上:signin / signup 在导入文件之后、测试运行之前执行;导入文件始终以 root 身份运行。若 signin / signup 期间出错,该错误将作为测试结果返回,并且可以像解析错误一样被匹配断言。该字段不支持用于升级测试。
auth
与signin/signup走真实校验流程不同,auth直接指定测试运行的权限身份,绕过了常规的登录校验代码。共有 4 种形态(对应源码中TestAuth枚举的Root/Namespace/Database/Record四变体,见 language-tests/src/tests/schema/mod.rs):
# 以 viewer 角色认证数据存储根 [env] auth = { level = "viewer" }# 以 viewer 角色认证 namespace `ns` [env] auth = { namespace = "ns", level = "viewer" }# 以 viewer 角色认证 namespace `ns` 与 database `db` [env] auth = { namespace = "ns", database = "db", level = "viewer" }# 在 namespace `ns`、database `db` 中,以访问定义 `access_definition` 认证,记录 id 为 `user:account` [env] auth = { namespace = "ns", database = "db", access = "access_definition", rid = "user:account" }level的可选值对应AuthLevel枚举(见 language-tests/src/tests/schema/mod.rs):owner(默认)、editor、viewer。该字段同样不支持用于升级测试。
capabilities
以表形式配置数据库运行时的能力,可以像 SurrealDB 二进制 / Rust SDK 一样禁用函数、网络目标、HTTP 路由与脚本能力。默认全部能力开启。底层映射到surrealdb_core::dbs::capabilities中的FuncTarget、NetTarget、MethodTarget、RouteTarget、ExperimentalTarget(见 language-tests/src/tests/schema/mod.rs)。可配置项包括:
scripting:是否允许脚本(默认true);quest_access、live_query_notifications(默认true);allow_functions/deny_functions:函数允许/拒绝列表;allow_net/deny_net:网络目标允许/拒绝列表;allow_rpc/deny_rpc:RPC 方法允许/拒绝列表;allow_http/deny_http:HTTP 路由允许/拒绝列表;allow_experimental/deny_experimental:实验特性允许/拒绝列表。
该字段不支持用于升级测试。
planner-strategy
控制测试在哪些查询规划器策略下执行,测试会为列出的每个策略各运行一次,每次使用独立的全新数据存储。可选策略:
"best-effort-ro":对只读语句尝试新规划器,若返回Unimplemented则静默回退到旧的 compute 执行器;"all-ro":要求所有只读语句都使用新规划器,若新规划器无法处理非 DDL/DML 语句则测试直接报错(不再静默回退);DDL/DML 语句(CREATE、UPDATE、DELETE、DEFINE 等)无论如何都会回退;"compute-only":完全跳过新规划器,所有语句一律使用旧的 compute 执行器。
省略时的默认值是["compute-only", "all-ro"],即测试默认执行两次:一次在旧 compute 执行器下,一次要求使用新规划器。此默认行为由 language-tests/src/tests/schema/mod.rs 中的default_planner_strategy以及NewPlannerStrategyConfig::DEFAULT_STRATEGIES(见 language-tests/src/tests/schema/mod.rs)共同确认。该枚举最终转换为surrealdb_core::dbs::NewPlannerStrategy的三种对应策略(见 language-tests/src/tests/schema/mod.rs)。
# 只在新的执行器下运行(收窄默认的双策略运行) [env] planner-strategy = ["all-ro"]# 只在旧 compute 执行器下运行(例如新规划器尚未支持的功能) [env] planner-strategy = ["compute-only"]redact-volatile-explain-attrs
一个可选的补充配置(源码中存在,见 language-tests/src/tests/schema/mod.rs):是否隐去EXPLAIN ANALYZE输出中易变的耗时字段,使输出对测试断言确定化。语言测试框架中默认开启;若确实需要真实耗时,可显式设为false。
七、多后端、双执行器的测试执行流程
综合源码可以还原出一次典型cargo run run的完整流程:
- 加载用例:
CaseSet::load_surrealql_files递归遍历测试根目录,收集所有.surql文件(见 language-tests/src/tests/case/mod.rs),逐个解析内嵌 TOML 配置生成TestCase。 - 过滤:依次应用
test.run、env.backend、路径过滤器、--no-wip、--no-results、test.version/test.importing-version等过滤条件(见 language-tests/src/cmd/run/mod.rs)。 - 展开:对每个用例按
planner-strategy展开为多个运行任务(TestRunConfig组合了后端与规划器策略,见 language-tests/src/cmd/run/mod.rs)。 - 调度执行:
Schedular以Semaphore控制并发度,普通任务占用 1 个许可,sequential任务独占全部许可(见 language-tests/src/runner/mod.rs)。 - 结果处理:执行后与
[test.results]声明的预期进行精确比较、粗略比较(跳过字段)或匹配表达式校验,最后按--results模式决定是否回写文件,并输出报告。
八、升级测试:验证跨版本数据库迁移
除常规语言测试外,该套件还包含升级测试(upgrade子命令),用于验证旧版本数据存储升级到新版本后的行为。其 CLI 参数(见 language-tests/src/cli.rs)包括:
-f, --from <VERSIONS>:升级的起始版本,可以是版本号,也可以是本地 surrealdb 代码库路径(必填,逗号分隔多个值);-t, --to <VERSIONS>:升级的目标版本,同样可以是版本号或路径(必填,逗号分隔);--backend <BACKEND>:升级测试的后端,可选rocksdb/surrealkv,默认surrealkv;--allow-download:跳过从 GitHub 下载旧版二进制的确认提示;--keep-files:测试结束后不清理生成的文件;- 以及
--no-wip、--no-results、-j、--results等与test子命令一致的选项。
升级测试相关实现位于 language-tests/src/cmd/upgrade/,其中binaries.rs负责旧版二进制下载、process.rs负责进程管理、protocol.rs负责与服务器通信。启用upgradefeature 后,工具才能编译该子命令(见 language-tests/src/main.rs)。升级测试的用例集中在 language-tests/tests/upgrade/,这解释了[test.importing-version]这类字段的存在意义:升级后的数据存储版本与运行测试的数据存储版本可以不同。
九、测试用例的实际组织与规模
仓库中的测试用例按主题组织在 language-tests/tests/ 下,主要包括:
language/:语言特性测试,细分statements(语句)、functions(函数)、expression(表达式)、idiom(idiom)、planner(规划器)、indexes(索引)、graph(图)、control_flow(控制流)、primitive(基础类型)等子目录,其中statements与functions各有数百个用例;parsing/:解析相关测试,含basic、strings、datetime、bytes、errors、deprecate等;access/:访问控制测试,按root、namespace、database、record分层;api/:API 相关测试(body、config、errors、methods、paths、permissions等);reproductions/:针对具体 issue 的回归测试,文件名直接使用 issue 编号,例如7132_phantom_unique_index_relation.surql、7199_bm25_match_bind_variable.surql、7229_knn_k_distance_bypasses_hnsw.surql,配合[test]中的issue字段,可以清晰追溯到缺陷来源;self_tests/:对测试框架自身的自测;harness/:提供assert.surql、rng.surql等被其他用例导入的辅助文件;upgrade/:跨版本升级测试。
这种“按功能目录 + 按 issue 编号命名 + 内嵌 TOML 自描述”的组织方式,使得测试套件本身即可作为 SurrealQL 行为的活文档:想了解某个语句或函数在 SurrealDB 中的真实语义,直接在对应目录下搜索.surql测试即可。
结语
SurrealDB 的 SurrealQL 语言测试套件是一套自包含、可扩展、后端无关的测试基础设施。它的核心设计可以概括为三点:用 SurrealQL 文件承载测试(普通解析器即可解析,天然贴近真实使用);用注释内嵌 TOML 声明配置([test]描述测试本身,[env]描述运行环境,所有键可选且有默认值);用多机制校验结果(精确值、skip-*粗略相等、match匹配表达式,覆盖确定性与非确定性输出)。配合多存储后端(mem / rocksdb / surrealkv / tikv)、双执行器策略(compute-only / all-ro / best-effort-ro)与跨版本升级测试,它既服务于 SurrealDB 自身的回归保障,也为贡献者提供了一条编写新测试、验证新行为的低门槛路径——无论是报告缺陷、复现 issue,还是验证新规划器行为,都可以从在 language-tests/tests 下新增一个带/** */配置注释的.surql文件开始。
【免费下载链接】surrealdbA scalable, distributed, collaborative, document-graph database, for the realtime web项目地址: https://gitcode.com/GitHub_Trending/su/surrealdb
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考