ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

GoNavi 数据源契约测试工具(contract-test)实战指南:可筛选的确定性边界测试矩阵与稳定 JSON 报告

GoNavi 数据源契约测试工具(contract-test)实战指南:可筛选的确定性边界测试矩阵与稳定 JSON 报告 数据库客户端桌面应用MCP 服务【免费下载链接】GoNaviHigh-performance multi-data-source database client — ~30MB, AI MCP ready, zero Electron bloat. | 高性能多数据源数据库客户端约 30MBAI 与 MCP 就绪告别 Electron 膨胀。项目地址https://gitcode.com/gh_mirrors/go/GoNavi点击查看免费下载GoNavi高性能多数据源数据库客户端在后端internal/db与internal/app中沉淀了大量与数据源行为边界相关的测试这些测试分散且难以统一观测。tools/contract-test是一个纯本地、不触碰外部服务的契约测试编排器它把这些边界测试收敛为一个可筛选、可排序、输出稳定 JSON 的测试矩阵报告。读完本文你将掌握该工具的筛选语法、内置契约矩阵、Docker 可选 fixture 的运行与降级语义以及如何把稳定报告接入 CI 与诊断包解析。一、工具定位编排已有测试 seam而不是新增测试tools/contract-test的 README 开宗明义它只编排已有的测试 seam不修改数据源能力注册也不连接或写入外部服务。从源码结构看main.go它本质上是一个测试调度器 报告生成器内置一张默认契约矩阵defaultContracts()main.go每条契约声明了数据源、能力、fixture 类型以及对应的 Go 测试调用信息包路径、-run正则、构建标签根据用户筛选条件挑选契约通过go test子进程或 Docker Compose fixture 执行把结果汇总为结构化的 JSON 报告输出到 stdout供 CI 与诊断包解析。这意味着契约本身并不是新写的测试而是对已有边界测试的再组织。例如矩阵中的 PostgreSQL 逻辑路径契约实际指向的是 contract_postgres_test.go 中既有的测试函数。二、快速上手从仓库根目录运行工具以 Go 单文件命令的形式位于 tools/contract-test无需安装任何额外依赖从仓库根目录直接执行即可# 运行全部默认契约不含 Docker 容器 fixture go run ./tools/contract-test # 按数据源 能力组合筛选 go run ./tools/contract-test --data-source sqlite --capability cancel # 使用别名并附带 Docker 容器 fixture go run ./tools/contract-test --source redis --capability cursor --containers执行后 stdout 输出一个 JSON 报告进程退出码语义为0全部通过、1存在失败契约、2配置或仓库根定位出错见 main.go 的reportExitCode。例如筛选无匹配契约时报告会携带error: no contracts matched the supplied filters且退出码为2。三、筛选语法任意匹配 分组交集3.1 三种等价的数据源参数名--data-source可重复使用也可接收逗号分隔值同时提供两个别名--source、--datasourcemain.go。解析时会先做归一化normalizeDataSourcesmain.go输入写法归一化结果sqlitesqlitepg/postgresqlpostgreseselasticsearchoceanbase-oracle/oceanbase_oracleoceanbase3.2 能力的归一化别名--capability同样支持重复与逗号分隔别名映射见normalizeCapabilitiesmain.go输入写法归一化结果cancellationcancelpermissionspermissionpartial/partial-resultpartial-resultsbody-limit/response-body/response-limitresponse-body-limitcursor、timeout等保持不变筛选时所有输入会被转换为小写、去空白、去重并排序normalizeValuesmain.go因此--data-source SQLite,PG 与--datasource sqlite,postgresql等价。3.3 筛选语义组内任一匹配组间同时生效每个筛选组数据源、能力内部按任一匹配OR选择两个筛选组之间是同时生效AND关系由selectContracts实现main.go。核心判定matchesAnymain.go未提供任何筛选条件 → 匹配全部只提供--source sqlite,redis→ 匹配 SQLite 与 Redis 的所有能力契约提供--source sqlite,redis --capability cancel,cursor→ 同时命中 SQLite 的取消/超时契约与 Redis 的游标契约。main_test.go 的TestSelectContractsUsesAnyRequestedDataSourceOrCapability验证了这一点筛选redis,sqlitecancel,cursor恰好选中redis.cursor与sqlite.query-context两条契约。四、默认契约矩阵五种数据源的本地 fixture默认契约在defaultContracts()中定义并被排序按契约 ID 字典序全部契约在无 Docker 环境下即可运行。汇总如下数据源能力fixture底层测试SQLite取消、超时内存 SQLite只读查询^TestSQLiteContractReadOnlyQueryContextBoundaries$位于 contract_sqlite_test.go带构建标签gonavi_sqlite_driverElasticsearch响应体上限httptestHTTP 服务^TestLegacyElasticsearchQueryResponseLimits$位于 elasticsearch_console_test.go带构建标签gonavi_elasticsearch_driverRedis游标进程内 cursor/state fixture^(TestParseRedisScanCursor\|TestDBGetTablesRedisCursorState)$位于 methods_redis_cursor_test.go 与 methods_db_metadata_retry_test.goPostgreSQL 逻辑路径取消、超时、权限进程内 fake driver / HeadlessRuntime对应 methods_db_cancel_test.go、contract_postgres_test.go、headless_write_policy_test.goOceanBase Oracle 逻辑路径部分结果进程内 metadata fixture^TestDBGetObjectsMarksExtensionMetadataFailuresPartial$位于 methods_db_metadata_retry_test.go契约 ID 采用数据源.能力的稳定命名如sqlite.query-context、redis.container-cursor其中 SQLite 与 Elasticsearch 契约在执行go test时会通过-tags携带各自的驱动构建标签见 main.go保证只在对应驱动代码就绪时运行。4.1 SQLite 契约示例只读、不落地、上下文边界SQLite 契约对应的测试 contract_sqlite_test.go 刻意只使用:memory:内存库验证三条上下文边界而不创建 schema、不改动用户数据库只读查询QueryContext(ctx, SELECT 42 AS answer)应返回正确列与行已取消的 contextcontext.WithCancel后立即cancel()查询须返回context.Canceled已过期的 deadlinecontext.WithDeadline到过去时间查询须返回context.DeadlineExceeded。4.2 PostgreSQL 契约示例不打开连接也能验证超时语义PostgreSQL 超时契约对应的 contract_postgres_test.go 不建立任何真实数据库连接而是通过newQueryExecutionContext构造一个Type: postgres、Timeout: 1、QueryTimeout: 7的连接配置断言生成的 context 带有约 7 秒的 deadline。这让矩阵可以绑定具体的 PostgreSQL 配置语义却完全不需要一个可用的 PostgreSQL 服务。五、可选容器契约Redis 游标的 Docker Compose 编排默认矩阵只使用本地 fixture只有redis.container-cursor契约main.go标记了RequiresContainer: true需要--containers或别名--with-containers见 main.go才会被选中。5.1 编排流程启动、探针、清理runOptionalRedisFixturemain.go按固定顺序执行用exec.LookPath(docker)检查 docker 可执行文件docker compose version检查 Compose 插件docker info --format {{.ServerVersion}}检查 daemon校验 fixture 文件 fixtures/redis.compose.yml 存在以--project-name gonavi-contract-pid启动up --detach --wait redis避免与其他项目冲突在容器内执行只读探针redis-cli --raw SCAN 0 COUNT 1无论探针结果如何先执行down --volumes --remove-orphans完成清理再判定结果。探针输出的游标必须为0即首轮 SCAN 即结束否则判定为container_cursor_invalid。整个编排受 90 秒containerTimeout约束清理步骤另有 30 秒的cleanupTimeoutmain.go。5.2 fixture 说明fixtures/redis.compose.yml 使用redis:7.4-alpine镜像并显式禁用持久化--save 、--appendonly no配合 1 秒间隔、10 次重试的redis-cli ping健康检查保证每次测试得到的是干净、可重复的临时实例。5.3 降级语义跳过或严格失败Docker 或镜像不可用时契约不会被当作失败而是以skipped状态输出到 JSON并附固定 reason见optionalContainerResultmain.go。可能的 reason 包括reason触发条件docker_unavailable找不到 docker 可执行文件docker_compose_unavailabledocker compose version失败docker_daemon_unavailabledocker info失败daemon 未启动container_fixture_missingcompose 文件缺失container_start_failed容器启动失败container_cleanup_failed清理失败即使探针成功也判定失败container_probe_failed探针命令执行失败container_cursor_invalid探针返回游标非0加上--strict-containers后上述任一跳过都会转为failed并导致退出码1。测试 main_test.go 验证了docker_unavailable在普通模式下的skipped与严格模式下的failed两种结果main_test.go 则验证了完整编排共执行 5 条命令compose version、docker info、up、exec 探针、down 清理且清理命令包含--volumes --remove-orphans。六、稳定 JSON 报告面向 CI 与诊断包的输出契约报告的可解析性是本工具的另一核心设计目标。README 明确报告只包含排序后的矩阵元数据、状态与固定失败原因不包含运行时长、临时目录或命令输出因此同一结果的 stdout 可稳定供 CI 与诊断包解析。6.1 报告结构报告由contractReport定义main.go使用固定 schemagonavi.contract-test/v1顶层包含schema固定版本标识selection本次筛选条件数据源、能力、是否含容器、是否严格容器模式summarytotal/passed/failed/skipped四类统计results每条契约的结果数组每项含id、dataSource、capabilities、fixture、status、可选的reason与execution包路径、-run正则、构建标签error仅在配置错误如仓库根未找到、筛选无匹配时出现。JSON 由writeReport以 2 空格缩进输出并关闭 HTML 转义main.go保证两次运行同一输入产出字节级一致的文本。6.2 稳定性由测试锁定main_test.go 的TestWriteReportIsStableJSON专门守护这份输出契约它断言两次序列化结果完全相同、报告中不得包含duration等易变字段、且必须携带gonavi.contract-test/v1schema。这意味着 CI 与诊断包可以放心地把报告内容写入缓存或用于 diff 比对。6.3 Go 测试调用参数非容器契约通过runGoTestmain.go执行go test参数固定为go test [-tags tags] package -run regex -count1 -timeouttimeout-count1禁止缓存、-timeout默认 2 分钟可用--test-timeout调整必须大于零见 main.go。测试若超时报告 reason 为runner_timeout其他失败 reason 为go_test_failed。契约缺少 Go 调用信息时 reason 为matrix_configuration_error。--verbose模式下失败契约的原始子命令输出会写到 stderrlogFailuremain.go方便本地排查但不会污染 stdout 的报告。七、完整参数速查参数别名类型默认值说明--data-source--source、--datasource可重复 / 逗号分隔全部数据源筛选自动归一化与去重排序--capability无可重复 / 逗号分隔全部能力筛选自动归一化与去重排序--containers--with-containers布尔false启用 Docker Compose 可选 fixture--strict-containers无布尔false将可选容器跳过转为失败--verbose无布尔false把失败命令输出写到 stderr--test-timeout无时长2m单条契约的 Go 测试超时--root无路径.仓库根目录或其下任意目录工具会向上查找go.mod见findRepositoryRootmain.go八、典型使用场景本地开发回归改动了internal/db或internal/app的查询上下文、取消/超时逻辑后运行go run ./tools/contract-test快速确认契约矩阵未回归。CI 稳定断言把 JSON 报告输出存档或对比基准利用稳定 schema 与固定 reason 做差异检测--strict-containers可让容器依赖成为硬性要求。诊断包取证reproduction bundle / 诊断包可解析同一份报告无需复现命令输出遇到容器类问题时可先用--verbose在本地复现完整命令序列。定向验证驱动能力例如只验证 Redis 游标能力go run ./tools/contract-test --source redis --capability cursor需要真容器编排时追加--containers。九、小结tools/contract-test用不到 600 行的单文件命令main.go把 GoNavi 分散在 internal/db 与 internal/app 中的数据源边界测试收敛成一张可筛选、可排序、可编程消费的契约矩阵本地 fixture 保证默认零外部依赖Docker 可选 fixture 以明确的降级 reason 兜底稳定 JSON 报告则让 CI 与诊断工具获得一致的消费契约。对维护多数据源客户端的人来说它提供了一套边界行为即契约、契约即可观测的轻量实践范式。赞分享数据库客户端桌面应用MCP 服务【免费下载链接】GoNaviHigh-performance multi-data-source database client — ~30MB, AI MCP ready, zero Electron bloat. | 高性能多数据源数据库客户端约 30MBAI 与 MCP 就绪告别 Electron 膨胀。项目地址https://gitcode.com/gh_mirrors/go/GoNavi点击查看免费下载相关推荐Handsontable Playwright 功能型 E2E 测试体系六腿矩阵、fixture 契约与确定性工程Handsontable Playwright 功能型 E2E 测试体系六腿矩阵、fixture 契约与确定性工程 Handsontable 在 tests/前端UI组件SoundSwitch 音频管理测试工程深度解析SoundSwitch.Audio.Manager.Tests 的确定性测试策略与 COM 契约边界SoundSwitch 音频管理测试工程深度解析SoundSwitch.Audio.Manager.Tests 的确定性测试策略与 COM 契约边界 导读 S桌面应用gitsigns.nvim 测试指南命令体系、版本矩阵与确定性测试实践gitsigns.nvim 测试指南命令体系、版本矩阵与确定性测试实践 本篇技术指南围绕 gitsigns.nvim 仓库的 etc/testing.md h开发工具上一篇猫抓浏览器扩展如何轻松获取网页视频音频资源的完整指南下一篇猫抓浏览器插件完整指南网页媒体资源嗅探高效方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表