From 0340bc4b8e027c9d78c9514f4c22a96c01f0ddb6 Mon Sep 17 00:00:00 2001 From: hoteas <925970985@qq.com> Date: Sun, 19 Apr 2026 09:44:15 +0800 Subject: [PATCH] =?UTF-8?q?feat(app):=20=E5=A2=9E=E5=BC=BA=E4=BC=98?= =?UTF-8?q?=E9=9B=85=E5=81=9C=E6=9C=BA=E9=80=BB=E8=BE=91=E4=B8=8E=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 inFlight 原子计数器以跟踪当前处理的请求数 - 更新 initiateGracefulShutdown 方法,支持每秒检测在途请求,优化停机时长 - 修改日志信息,提供更清晰的停机状态反馈 - 更新 DrainTimeout 注释,明确最长等待时长与检测机制 --- application.go | 29 +- example/debug-e1b6ef.log | 1 + example/tpt/swagger/app/api-spec.json | 2342 +------------------------ example/tpt/swagger/app/index.html | 22 +- 4 files changed, 93 insertions(+), 2301 deletions(-) create mode 100644 example/debug-e1b6ef.log diff --git a/application.go b/application.go index 28a360b..ad3b5a5 100644 --- a/application.go +++ b/application.go @@ -40,8 +40,9 @@ type Application struct { *http.Server http.Handler shuttingDown atomic.Bool // 停机标志,置为 true 后新请求立即返回 503 + inFlight atomic.Int64 // 当前正在处理的请求数(不含已返回 503 的) shutdownOnce sync.Once // 保证多路触发(信号/关窗口)只执行一次 - DrainTimeout time.Duration // 返回 503 后等 nginx 切流的时长,默认 5s + DrainTimeout time.Duration // 返回 503 后等 nginx 切流的最长时长,默认 5s(每 1s 检测在途请求,为 0 则立即进入 Shutdown) ShutdownTimeout time.Duration // 等在途请求完成的最长时间,默认 30s } @@ -51,17 +52,37 @@ func (that *Application) ServeHTTP(w http.ResponseWriter, req *http.Request) { http.Error(w, "Service Unavailable", http.StatusServiceUnavailable) return } + that.inFlight.Add(1) + defer that.inFlight.Add(-1) that.handler(w, req) } // initiateGracefulShutdown 触发优雅停机,通过 sync.Once 保证多路触发只执行一次。 -// drain: 返回 503 后等待上游(nginx)完成流量切换的时长。 +// drain: 返回 503 后等待上游(nginx)完成流量切换的最长时长,每 1s 检测一次在途请求数, +// 若为 0 则立即进入 Shutdown,避免无谓等待。 // shutdown: 等待在途请求完成的最长时间。 func (that *Application) initiateGracefulShutdown(drain, shutdown time.Duration) { that.shutdownOnce.Do(func() { that.shuttingDown.Store(true) - that.Log.Infof("优雅停机:新请求已返回 503,等 %v 让 nginx 完成流量切换...", drain) - time.Sleep(drain) + that.Log.Infof("优雅停机:新请求已返回 503,最多等 %v 让 nginx 完成流量切换(每秒检测在途请求)...", drain) + + // 每秒检测一次,若无在途请求立即停机,否则最多等满 drain + tick := time.NewTicker(1 * time.Second) + defer tick.Stop() + deadline := time.Now().Add(drain) + for { + if n := that.inFlight.Load(); n == 0 { + that.Log.Infof("无在途请求,立即进入 Shutdown") + break + } else if time.Now().After(deadline) { + that.Log.Infof("drain 等待到达上限 %v,仍有 %d 个在途请求,强制进入 Shutdown", drain, n) + break + } else { + that.Log.Infof("drain 等待中,当前在途请求数=%d", n) + } + <-tick.C + } + ctx, cancel := context.WithTimeout(context.Background(), shutdown) defer cancel() that.Log.Infof("停止接受新连接,等进行中请求完成(最多 %v)...", shutdown) diff --git a/example/debug-e1b6ef.log b/example/debug-e1b6ef.log new file mode 100644 index 0000000..20e1765 --- /dev/null +++ b/example/debug-e1b6ef.log @@ -0,0 +1 @@ +{"sessionId":"e1b6ef","hypothesisId":"D","message":"partial_run_check","data":{"proj":"app","totalPaths":30,"visitedPaths":0,"isPartialRun":false}} diff --git a/example/tpt/swagger/app/api-spec.json b/example/tpt/swagger/app/api-spec.json index 4f9afec..f8c4c40 100644 --- a/example/tpt/swagger/app/api-spec.json +++ b/example/tpt/swagger/app/api-spec.json @@ -1,122 +1,9 @@ { "endpoints": [ { - "cases": [ - { - "name": "缓存全部测试", - "method": "GET", - "passed": true, - "response": { - "result": { - "cache_mode": "compatible", - "cleanup": "已清理所有测试缓存数据", - "name": "数据库缓存测试", - "success": true, - "tests": [ - { - "cached_value": { - "active": true, - "count": 123, - "name": "测试数据" - }, - "name": "1. 基础 set/get 测试", - "result": true - }, - { - "after_exists": false, - "before_exists": true, - "name": "2. delete 删除缓存测试", - "result": true - }, - { - "immediate_exists": true, - "name": "3. 过期时间测试(短超时)", - "note": "设置了2秒过期,可等待后再次访问验证过期", - "result": true - }, - { - "name": "4. 不存在的 key 读取测试", - "result": true, - "value": null - }, - { - "first": "第一次值", - "name": "5. 重复 set 同一个 key 测试", - "result": true, - "second": "第二次值", - "third": { - "version": 3 - } - }, - { - "after": { - "a": false, - "b": false, - "c": false - }, - "before": { - "a": true, - "b": true, - "c": true - }, - "name": "6. 通配删除测试 (key*)", - "result": true - }, - { - "bool": true, - "float": 3.14159, - "int": 12345, - "map": { - "key": "value", - "num": 100 - }, - "name": "7. 不同数据类型存储测试", - "result": true, - "slice": [ - 1, - 2, - 3, - "four", - { - "five": 5 - } - ], - "string": "字符串值" - }, - { - "name": "8. 自定义超时时间参数测试", - "result": true, - "value": "长期数据" - }, - { - "name": "9. 缓存表状态查询", - "new_table_count": 0, - "new_table_name": "hotime_cache", - "result": true - } - ] - }, - "status": 0 - }, - "expect": { - "result": { - "cache_mode": "sample", - "cleanup": "sample", - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample", - "result": true - } - ] - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "cache", - "method": "GET", + "method": "POST", "params": [], "path": "/app/cache/all", "project": "app", @@ -124,27 +11,9 @@ "tested": true }, { - "cases": [ - { - "name": "批量缓存测试", - "method": "GET", - "passed": true, - "response": { - "result": { - "message": "批量缓存测试完成,请查看控制台输出和日志文件" - }, - "status": 0 - }, - "expect": { - "result": { - "message": "sample" - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "cache", - "method": "GET", + "method": "POST", "params": [], "path": "/app/cache/batch", "project": "app", @@ -152,80 +21,9 @@ "tested": true }, { - "cases": [ - { - "name": "兼容模式测试", - "method": "GET", - "passed": true, - "response": { - "result": { - "success": true, - "test_name": "兼容模式白盒测试", - "tests": [ - { - "mode": "compatible", - "name": "1. 查询当前缓存模式", - "result": true - }, - { - "count": 0, - "data": [], - "legacy_table": "cached", - "name": "2. 查询老表cached现有数据", - "result": true - }, - { - "count": 0, - "data": [], - "name": "3. 查询新表hotime_cache现有数据", - "new_table": "hotime_cache", - "result": true - }, - { - "cache_api_result": null, - "key_in_new_table": false, - "name": "4. 测试兼容模式老表回退读取", - "result": false, - "test_key": "test_compat_fallback_1775925593923602500" - }, - { - "name": "5. 测试兼容模式写新删老", - "result": false, - "step1_legacy_before": true, - "step2_new_after": false, - "step3_legacy_after_deleted": false - }, - { - "after_legacy_deleted": false, - "after_new_deleted": false, - "before_legacy": true, - "before_new": true, - "name": "6. 测试兼容模式删除(删除两表)", - "result": false - } - ], - "timestamp": "2026-04-12 00:39:53" - }, - "status": 0 - }, - "expect": { - "result": { - "success": true, - "test_name": "sample", - "tests": [ - { - "name": "sample", - "result": true - } - ], - "timestamp": "sample" - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "cache", - "method": "GET", + "method": "POST", "params": [], "path": "/app/cache/compat", "project": "app", @@ -263,23 +61,9 @@ "tested": true }, { - "cases": [ - { - "name": "result是布尔", - "method": "GET", - "passed": true, - "response": { - "result": true, - "status": 0 - }, - "expect": { - "result": true, - "status": 0 - } - } - ], + "cases": null, "ctr": "expect_demo", - "method": "GET", + "method": "POST", "params": [], "path": "/app/expect_demo/bool_result", "project": "app", @@ -287,96 +71,19 @@ "tested": true }, { - "cases": [ - { - "name": "名称为空-缺少必填字段", - "method": "POST", - "passed": true, - "form": { - "name": "" - }, - "response": { - "error": { - "msg": "名称不能为空", - "type": "请求参数异常" - }, - "result": { - "msg": "名称不能为空", - "type": "请求参数异常" - }, - "status": 3 - }, - "expect": { - "error": { - "msg": "名称不能为空", - "type": "请求参数异常" - }, - "result": { - "msg": "名称不能为空", - "type": "请求参数异常" - }, - "status": 3 - } - }, - { - "name": "名称正确-结构+值校验", - "method": "POST", - "passed": true, - "form": { - "name": "测试商品" - }, - "response": { - "result": { - "created": true, - "id": 1, - "name": "测试商品" - }, - "status": 0 - }, - "expect": { - "result": { - "created": true, - "id": 1, - "name": "sample" - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "expect_demo", "method": "POST", - "params": [ - { - "name": "name", - "required": true, - "type": "string", - "example": "测试商品", - "in": "form" - } - ], + "params": [], "path": "/app/expect_demo/error_demo", "project": "app", "summary": "错误先行+正确请求完整校验", "tested": true }, { - "cases": [ - { - "name": "result是小数", - "method": "GET", - "passed": true, - "response": { - "result": 3.14, - "status": 0 - }, - "expect": { - "result": 1, - "status": 0 - } - } - ], + "cases": null, "ctr": "expect_demo", - "method": "GET", + "method": "POST", "params": [], "path": "/app/expect_demo/float_result", "project": "app", @@ -384,33 +91,9 @@ "tested": true }, { - "cases": [ - { - "name": "result是Map-校验字段名+类型+值", - "method": "GET", - "passed": true, - "response": { - "result": { - "id": 1, - "in_stock": true, - "name": "示例商品", - "price": 19.9 - }, - "status": 0 - }, - "expect": { - "result": { - "id": 1, - "in_stock": true, - "name": "sample", - "price": 1 - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "expect_demo", - "method": "GET", + "method": "POST", "params": [], "path": "/app/expect_demo/map_result", "project": "app", @@ -418,73 +101,9 @@ "tested": true }, { - "cases": [ - { - "name": "深层嵌套Map+Slice+Map", - "method": "GET", - "passed": true, - "response": { - "result": { - "customer": { - "id": 1, - "name": "张三", - "phone": "13800138000" - }, - "extra": { - "delivery": { - "address": "XX路1号", - "fee": 5 - } - }, - "id": 100, - "items": [ - { - "goods_name": "苹果", - "id": 1, - "price": 3.5, - "quantity": 5 - }, - { - "goods_name": "香蕉", - "id": 2, - "price": 2, - "quantity": 10 - } - ], - "title": "测试订单" - }, - "status": 0 - }, - "expect": { - "result": { - "customer": { - "id": 1, - "name": "sample", - "phone": "sample" - }, - "extra": { - "delivery": { - "address": "sample", - "fee": 1 - } - }, - "id": 1, - "items": [ - { - "goods_name": "sample", - "id": 1, - "price": 1, - "quantity": 1 - } - ], - "title": "sample" - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "expect_demo", - "method": "GET", + "method": "POST", "params": [], "path": "/app/expect_demo/nested_result", "project": "app", @@ -492,29 +111,9 @@ "tested": true }, { - "cases": [ - { - "name": "有Verify值断言", - "method": "GET", - "passed": true, - "response": { - "result": { - "data": "无预期校验", - "id": 1 - }, - "status": 0 - }, - "expect": { - "result": { - "data": "sample", - "id": 1 - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "expect_demo", - "method": "GET", + "method": "POST", "params": [], "path": "/app/expect_demo/no_expect", "project": "app", @@ -522,23 +121,9 @@ "tested": true }, { - "cases": [ - { - "name": "result是整数", - "method": "GET", - "passed": true, - "response": { - "result": 42, - "status": 0 - }, - "expect": { - "result": 1, - "status": 0 - } - } - ], + "cases": null, "ctr": "expect_demo", - "method": "GET", + "method": "POST", "params": [], "path": "/app/expect_demo/number_result", "project": "app", @@ -546,37 +131,9 @@ "tested": true }, { - "cases": [ - { - "name": "result直接是Slice", - "method": "GET", - "passed": true, - "response": { - "result": [ - { - "id": 1, - "name": "标签A" - }, - { - "id": 2, - "name": "标签B" - } - ], - "status": 0 - }, - "expect": { - "result": [ - { - "id": 1, - "name": "sample" - } - ], - "status": 0 - } - } - ], + "cases": null, "ctr": "expect_demo", - "method": "GET", + "method": "POST", "params": [], "path": "/app/expect_demo/slice_result", "project": "app", @@ -584,23 +141,9 @@ "tested": true }, { - "cases": [ - { - "name": "result是字符串", - "method": "GET", - "passed": true, - "response": { - "result": "操作成功", - "status": 0 - }, - "expect": { - "result": "样本", - "status": 0 - } - } - ], + "cases": null, "ctr": "expect_demo", - "method": "GET", + "method": "POST", "params": [], "path": "/app/expect_demo/string_result", "project": "app", @@ -608,413 +151,29 @@ "tested": true }, { - "cases": [ - { - "name": "名称为空", - "method": "POST", - "passed": true, - "form": { - "name": "" - }, - "response": { - "error": { - "msg": "名称不能为空", - "type": "请求参数异常" - }, - "result": { - "msg": "名称不能为空", - "type": "请求参数异常" - }, - "status": 3 - }, - "expect": { - "error": { - "msg": "名称不能为空", - "type": "请求参数异常" - }, - "result": { - "msg": "名称不能为空", - "type": "请求参数异常" - }, - "status": 3 - } - }, - { - "name": "写入并校验DB+响应", - "method": "POST", - "passed": true, - "form": { - "name": "verify_test" - }, - "response": { - "result": { - "id": 107, - "name": "verify_test" - }, - "status": 0 - }, - "expect": { - "result": { - "id": 1, - "name": "sample" - }, - "status": 0 - } - }, - { - "name": "写入并校验DB-故意失败", - "method": "POST", - "passed": false, - "form": { - "name": "verify_fail" - }, - "response": { - "result": { - "id": 108, - "name": "verify_fail" - }, - "status": 0 - }, - "expect": { - "result": { - "id": 1, - "name": "sample" - }, - "status": 0 - }, - "verifyError": "test_batch.state 期望 99, 实际 0(接口写入 0,故意校验 99 演示失败效果)" - } - ], + "cases": null, "ctr": "expect_demo", "method": "POST", - "params": [ - { - "name": "name", - "required": true, - "type": "string", - "example": "verify_fail", - "in": "form" - } - ], + "params": [], "path": "/app/expect_demo/verify_demo", "project": "app", "summary": "Verify完整范式演示", "tested": true }, { - "cases": [ - { - "name": "不传table参数", - "method": "GET", - "passed": true, - "response": { - "error": { - "msg": "请提供 table 参数", - "type": "内部系统异常" - }, - "result": { - "msg": "请提供 table 参数", - "type": "内部系统异常" - }, - "status": 1 - }, - "expect": { - "error": { - "msg": "请提供 table 参数", - "type": "内部系统异常" - }, - "result": { - "msg": "请提供 table 参数", - "type": "内部系统异常" - }, - "status": 1 - } - }, - { - "name": "DESCRIBE admin", - "method": "GET", - "passed": true, - "query": { - "table": "admin" - }, - "response": { - "result": { - "columns": [ - { - "Default": null, - "Extra": "auto_increment", - "Field": "id", - "Key": "PRI", - "Null": "NO", - "Type": "int(11) unsigned" - }, - { - "Default": null, - "Extra": "", - "Field": "name", - "Key": "", - "Null": "YES", - "Type": "varchar(100)" - }, - { - "Default": null, - "Extra": "", - "Field": "phone", - "Key": "UNI", - "Null": "YES", - "Type": "varchar(20)" - }, - { - "Default": "0", - "Extra": "", - "Field": "state", - "Key": "", - "Null": "YES", - "Type": "int(2)" - }, - { - "Default": null, - "Extra": "", - "Field": "password", - "Key": "", - "Null": "YES", - "Type": "varchar(100)" - }, - { - "Default": "0", - "Extra": "", - "Field": "role_id", - "Key": "", - "Null": "YES", - "Type": "int(11)" - }, - { - "Default": null, - "Extra": "", - "Field": "title", - "Key": "", - "Null": "YES", - "Type": "varchar(100)" - }, - { - "Default": null, - "Extra": "", - "Field": "create_time", - "Key": "", - "Null": "YES", - "Type": "datetime" - }, - { - "Default": null, - "Extra": "", - "Field": "modify_time", - "Key": "", - "Null": "YES", - "Type": "datetime" - } - ], - "sample_data": [ - { - "create_time": "2026-03-20 02:32:47", - "id": 1, - "modify_time": "2026-03-20 02:32:47", - "name": "超级管理员", - "password": "admin123", - "phone": "13800000001", - "role_id": 1, - "state": 1, - "title": "系统管理员" - }, - { - "create_time": "2026-03-20 02:32:47", - "id": 2, - "modify_time": "2026-03-20 02:32:47", - "name": "编辑员", - "password": "editor123", - "phone": "13800000002", - "role_id": 2, - "state": 1, - "title": "内容编辑" - }, - { - "create_time": "2026-03-20 02:32:47", - "id": 3, - "modify_time": "2026-03-20 02:32:47", - "name": "审核员", - "password": "review123", - "phone": "13800000003", - "role_id": 3, - "state": 1, - "title": "内容审核" - }, - { - "create_time": "2026-03-20 02:43:03", - "id": 6, - "modify_time": "2026-03-20 02:43:03", - "name": "测试管理员_1773974584", - "password": "test123456", - "phone": "13873974584", - "role_id": 1, - "state": 1, - "title": "更新后的职位" - }, - { - "create_time": "2026-03-20 02:43:09", - "id": 9, - "modify_time": "2026-03-20 02:43:09", - "name": "测试管理员_1773974590", - "password": "test123456", - "phone": "13873974590", - "role_id": 1, - "state": 1, - "title": "更新后的职位" - }, - { - "create_time": "2026-03-20 02:50:47", - "id": 12, - "modify_time": "2026-03-20 02:50:47", - "name": "测试管理员_1773975048", - "password": "test123456", - "phone": "13873975048", - "role_id": 1, - "state": 1, - "title": "更新后的职位" - }, - { - "create_time": "2026-03-20 02:57:19", - "id": 18, - "modify_time": "2026-03-20 02:57:19", - "name": "测试管理员_1773975440", - "password": "test123456", - "phone": "13873975440", - "role_id": 1, - "state": 1, - "title": "更新后的职位" - }, - { - "create_time": "2026-03-29 16:47:48", - "id": 22, - "modify_time": "2026-03-29 16:47:48", - "name": "测试管理员_1774802868", - "password": "test123456", - "phone": "13874802868", - "role_id": 1, - "state": 1, - "title": "更新后的职位" - }, - { - "create_time": "2026-03-29 16:47:49", - "id": 25, - "modify_time": "2026-03-29 16:47:50", - "name": "测试管理员_1774802869", - "password": "test123456", - "phone": "13874802869", - "role_id": 1, - "state": 1, - "title": "更新后的职位" - }, - { - "create_time": "2026-03-29 16:54:20", - "id": 28, - "modify_time": "2026-03-29 16:54:20", - "name": "测试管理员_1774803260", - "password": "test123456", - "phone": "13874803260", - "role_id": 1, - "state": 1, - "title": "更新后的职位" - } - ], - "table": "admin" - }, - "status": 0 - }, - "expect": { - "result": { - "columns": [], - "sample_data": [], - "table": "sample" - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "mysql", - "method": "GET", - "params": [ - { - "name": "table", - "required": false, - "type": "string", - "example": "admin", - "in": "query" - } - ], + "method": "POST", + "params": [], "path": "/app/mysql/describe", "project": "app", "summary": "查询 MySQL 表结构", "tested": true }, { - "cases": [ - { - "name": "MySQL原生SQL", - "method": "GET", - "passed": true, - "response": { - "result": { - "name": "MySQL原生SQL测试", - "success": true, - "tests": [ - { - "count": 5, - "name": "Query 原生查询 (反引号)", - "result": true - }, - { - "affected": 1, - "name": "Exec 原生执行 (反引号)", - "result": true - }, - { - "count": 5, - "lastQuery": "SELECT id, title FROM `article` WHERE id IN (?, ?, ?, ?, ?) LIMIT 10", - "name": "IN (?) 非空数组展开", - "result": true - }, - { - "count": 0, - "lastQuery": "SELECT id, title FROM `article` WHERE 1=0 LIMIT 10", - "name": "IN (?) 空数组替换为1=0", - "result": true - }, - { - "count": 10, - "lastQuery": "SELECT id, title FROM `article` WHERE 1=1 LIMIT 10", - "name": "NOT IN (?) 空数组替换为1=1", - "result": true - } - ] - }, - "status": 0 - }, - "expect": { - "result": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample", - "result": true - } - ] - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "mysql", - "method": "GET", + "method": "POST", "params": [], "path": "/app/mysql/rawsql", "project": "app", @@ -1022,112 +181,9 @@ "tested": true }, { - "cases": [ - { - "name": "SHOW TABLES", - "method": "GET", - "passed": true, - "response": { - "result": { - "tables": [ - { - "Tables_in_test": "体育" - }, - { - "Tables_in_test": "军事" - }, - { - "Tables_in_test": "历史" - }, - { - "Tables_in_test": "地理" - }, - { - "Tables_in_test": "外语" - }, - { - "Tables_in_test": "天文" - }, - { - "Tables_in_test": "影音" - }, - { - "Tables_in_test": "数学" - }, - { - "Tables_in_test": "数学1" - }, - { - "Tables_in_test": "文学" - }, - { - "Tables_in_test": "生物" - }, - { - "Tables_in_test": "综合" - }, - { - "Tables_in_test": "admin" - }, - { - "Tables_in_test": "article" - }, - { - "Tables_in_test": "auth_role" - }, - { - "Tables_in_test": "auth_user" - }, - { - "Tables_in_test": "cached" - }, - { - "Tables_in_test": "ctg" - }, - { - "Tables_in_test": "history" - }, - { - "Tables_in_test": "hotime_cache" - }, - { - "Tables_in_test": "ibang0420_iqiyi" - }, - { - "Tables_in_test": "question" - }, - { - "Tables_in_test": "role" - }, - { - "Tables_in_test": "role_user" - }, - { - "Tables_in_test": "stroage" - }, - { - "Tables_in_test": "test_batch" - }, - { - "Tables_in_test": "user" - }, - { - "Tables_in_test": "version" - } - ] - }, - "status": 0 - }, - "expect": { - "result": { - "tables": [] - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "mysql", - "method": "GET", + "method": "POST", "params": [], "path": "/app/mysql/tables", "project": "app", @@ -1135,124 +191,9 @@ "tested": true }, { - "cases": [ - { - "name": "聚合函数", - "method": "GET", - "passed": true, - "response": { - "result": { - "name": "聚合函数测试", - "success": true, - "tests": [ - { - "count": 11, - "name": "Count 总数统计", - "result": true - }, - { - "count": 9, - "name": "Count 条件统计", - "result": true - }, - { - "lastQuery": "SELECT SUM(click_num) FROM `article` WHERE `state` =? ;", - "name": "Sum 求和 (单字段名)", - "result": true, - "sum": 12311 - }, - { - "avg": 1367.8889, - "lastQuery": "SELECT AVG(click_num) FROM `article` WHERE `state` =? ;", - "name": "Avg 平均值 (单字段名)", - "result": true - }, - { - "lastQuery": "SELECT MAX(click_num) FROM `article` WHERE `state` =? ;", - "max": 9999, - "name": "Max 最大值 (单字段名)", - "result": true - }, - { - "lastQuery": "SELECT MIN(sort) FROM `article` WHERE `state` =? ;", - "min": 1, - "name": "Min 最小值 (单字段名)", - "result": true - }, - { - "name": "GROUP BY 分组统计", - "result": true, - "stats": [ - { - "article_count": 4, - "avg_clicks": 450, - "ctg_id": 2, - "total_clicks": 1800 - }, - { - "article_count": 3, - "avg_clicks": 3461, - "ctg_id": 1, - "total_clicks": 10383 - }, - { - "article_count": 1, - "avg_clicks": 32, - "ctg_id": 3, - "total_clicks": 32 - }, - { - "article_count": 1, - "avg_clicks": 96, - "ctg_id": 4, - "total_clicks": 96 - } - ] - }, - { - "lastQuery": "SELECT SUM(`article`.`click_num`) FROM `article` WHERE `state` =? ;", - "match_single_field": false, - "name": "Sum 求和 (table.column 格式)", - "result": true, - "sum": 0 - }, - { - "name": "聚合函数一致性验证", - "result": false, - "summary": "Sum: 12311=0, Avg: 1367.8889=0, Max: 9999=0, Min: 1=0" - }, - { - "lastQuery": "SELECT SUM(`article`.`click_num`) FROM `article` LEFT JOIN `ctg` ON `article`.`ctg_id` = `ctg`.`id` WHERE `article`.`state` =? ;", - "name": "Sum 带 JOIN (table.column 格式)", - "result": true, - "sum": 0 - }, - { - "count": 9, - "lastQuery": "SELECT COUNT(*) FROM `article` LEFT JOIN `ctg` ON `article`.`ctg_id` = `ctg`.`id` WHERE `article`.`state` =? ;", - "name": "Count 带 JOIN", - "result": true - } - ] - }, - "status": 0 - }, - "expect": { - "result": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample" - } - ] - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "test", - "method": "GET", + "method": "POST", "params": [], "path": "/app/test/aggregate", "project": "app", @@ -1260,593 +201,9 @@ "tested": true }, { - "cases": [ - { - "name": "全部测试", - "method": "GET", - "passed": true, - "response": { - "result": { - "1_basic_crud": { - "name": "基础CRUD测试", - "success": true, - "tests": [ - { - "adminId": 40, - "lastQuery": "INSERT INTO `admin` (`password`,`role_id`,`title`,`create_time`,`modify_time`,`name`,`phone`,`state`) VALUES (?,?,?,NOW(),NOW(),?,?,?);", - "name": "Insert 插入测试 (admin表)", - "result": true - }, - { - "admin": { - "create_time": "2026-04-11 16:39:56", - "id": 40, - "modify_time": "2026-04-11 16:39:56", - "name": "测试管理员_1775925594", - "password": "test123456", - "phone": "13875925594", - "role_id": 1, - "state": 1, - "title": "测试职位" - }, - "name": "Get 获取单条记录测试", - "result": true - }, - { - "count": 5, - "name": "Select 单条件查询测试", - "result": true - }, - { - "count": 5, - "lastQuery": "SELECT * FROM `admin` WHERE `role_id` \u003e? AND `state` =? ORDER BY id DESC LIMIT 5 ;", - "name": "Select 多条件自动AND测试", - "result": true - }, - { - "affected": 1, - "name": "Update 更新测试", - "result": true - }, - { - "affected": 1, - "name": "Delete 删除测试", - "result": true - } - ] - }, - "2_condition_syntax": { - "name": "条件查询语法测试", - "success": true, - "tests": [ - { - "count": 3, - "name": "等于条件 (=)", - "result": true - }, - { - "count": 3, - "lastQuery": "SELECT id,title,state FROM `article` WHERE `state` !=? LIMIT 3 ;", - "name": "不等于条件 ([!])", - "result": true - }, - { - "count": 3, - "name": "大于小于条件 ([\u003e], [\u003c])", - "result": true - }, - { - "count": 3, - "name": "大于等于小于等于条件 ([\u003e=], [\u003c=])", - "result": true - }, - { - "count": 1, - "lastQuery": "SELECT id,title FROM `article` WHERE `title` LIKE ? LIMIT 3 ;", - "name": "LIKE 模糊查询 ([~])", - "result": true - }, - { - "count": 0, - "name": "右模糊查询 ([~!])", - "result": true - }, - { - "count": 3, - "lastQuery": "SELECT id,title,click_num FROM `article` WHERE `click_num` BETWEEN ? AND ? LIMIT 3 ;", - "name": "BETWEEN 区间查询 ([\u003c\u003e])", - "result": true - }, - { - "count": 3, - "name": "NOT BETWEEN 查询 ([\u003e\u003c])", - "result": true - }, - { - "count": 5, - "lastQuery": "SELECT id,title FROM `article` WHERE (`id` BETWEEN ? AND ? ) LIMIT 5 ;", - "name": "IN 查询", - "result": true - }, - { - "count": 5, - "name": "NOT IN 查询 ([!])", - "result": true - }, - { - "count": 3, - "name": "IS NULL 查询", - "result": true - }, - { - "count": 3, - "name": "IS NOT NULL 查询 ([!])", - "result": true - }, - { - "count": 3, - "lastQuery": "SELECT id,title,create_time FROM `article` WHERE create_time \u003e DATE_SUB(NOW(), INTERVAL 365 DAY) LIMIT 3 ;", - "name": "直接 SQL 片段查询 ([##])", - "result": true - }, - { - "count": 3, - "name": "显式 AND 条件", - "result": true - }, - { - "count": 5, - "name": "OR 条件", - "result": true - }, - { - "count": 5, - "lastQuery": "SELECT id,title,sort,state FROM `article` WHERE (( `click_num` \u003e? OR `sort` \u003e=? ) AND `state` =?) LIMIT 5 ;", - "name": "嵌套 AND/OR 条件", - "result": true - } - ] - }, - "3_chain_query": { - "name": "链式查询测试", - "success": true, - "tests": [ - { - "count": 9, - "name": "基本链式查询 Table().Where().Select()", - "result": true - }, - { - "count": 9, - "name": "链式 And 条件", - "result": true - }, - { - "count": 9, - "name": "链式 Or 条件", - "result": true - }, - { - "count": 5, - "name": "链式 Order 排序", - "result": true - }, - { - "count": 3, - "name": "链式 Limit 限制", - "result": true - }, - { - "article": { - "author": "管理员", - "id": 1, - "title": "数据库入门指南" - }, - "name": "链式 Get 获取单条", - "result": true - }, - { - "count": 9, - "name": "链式 Count 统计", - "result": true - }, - { - "count": 5, - "name": "链式 Page 分页", - "result": true - }, - { - "name": "链式 Group 分组", - "result": true, - "stats": [ - { - "cnt": 3, - "ctg_id": 1 - }, - { - "cnt": 4, - "ctg_id": 2 - }, - { - "cnt": 1, - "ctg_id": 3 - }, - { - "cnt": 1, - "ctg_id": 4 - } - ] - }, - { - "affected": 1, - "name": "链式 Update 更新", - "result": true - } - ] - }, - "4_join_query": { - "name": "JOIN查询测试", - "success": true, - "tests": [ - { - "count": 5, - "data": [ - { - "ctg_name": "新闻资讯", - "id": 1, - "title": "数据库入门指南" - }, - { - "ctg_name": "新闻资讯", - "id": 2, - "title": "新闻发布系统上线公告" - }, - { - "ctg_name": "新闻资讯", - "id": 11, - "title": "高点击量文章" - }, - { - "ctg_name": "技术文档", - "id": 3, - "title": "Go语言最佳实践" - }, - { - "ctg_name": "技术文档", - "id": 4, - "title": "API接口设计规范" - } - ], - "name": "LEFT JOIN 链式查询", - "result": true - }, - { - "count": 5, - "lastQuery": "SELECT `article`.`id`, `article`.`title`, `ctg`.`name` as ctg_name FROM `article` LEFT JOIN `ctg` ON `article`.`ctg_id` = `ctg`.`id` WHERE `article`.`state` =? LIMIT 5 ;", - "name": "传统 JOIN 语法", - "result": true - }, - { - "count": 5, - "data": [ - { - "admin_name": "超级管理员", - "ctg_name": "新闻资讯", - "id": 1, - "title": "数据库入门指南" - }, - { - "admin_name": "编辑员", - "ctg_name": "新闻资讯", - "id": 2, - "title": "新闻发布系统上线公告" - }, - { - "admin_name": "编辑员", - "ctg_name": "新闻资讯", - "id": 11, - "title": "高点击量文章" - }, - { - "admin_name": "超级管理员", - "ctg_name": "技术文档", - "id": 3, - "title": "Go语言最佳实践" - }, - { - "admin_name": "审核员", - "ctg_name": "技术文档", - "id": 4, - "title": "API接口设计规范" - } - ], - "name": "多表 JOIN", - "result": true - }, - { - "count": 5, - "name": "INNER JOIN", - "result": true - } - ] - }, - "5_aggregate": { - "name": "聚合函数测试", - "success": true, - "tests": [ - { - "count": 11, - "name": "Count 总数统计", - "result": true - }, - { - "count": 9, - "name": "Count 条件统计", - "result": true - }, - { - "lastQuery": "SELECT SUM(click_num) FROM `article` WHERE `state` =? ;", - "name": "Sum 求和 (单字段名)", - "result": true, - "sum": 12311 - }, - { - "avg": 1367.8889, - "lastQuery": "SELECT AVG(click_num) FROM `article` WHERE `state` =? ;", - "name": "Avg 平均值 (单字段名)", - "result": true - }, - { - "lastQuery": "SELECT MAX(click_num) FROM `article` WHERE `state` =? ;", - "max": 9999, - "name": "Max 最大值 (单字段名)", - "result": true - }, - { - "lastQuery": "SELECT MIN(sort) FROM `article` WHERE `state` =? ;", - "min": 1, - "name": "Min 最小值 (单字段名)", - "result": true - }, - { - "name": "GROUP BY 分组统计", - "result": true, - "stats": [ - { - "article_count": 4, - "avg_clicks": 450, - "ctg_id": 2, - "total_clicks": 1800 - }, - { - "article_count": 3, - "avg_clicks": 3461, - "ctg_id": 1, - "total_clicks": 10383 - }, - { - "article_count": 1, - "avg_clicks": 32, - "ctg_id": 3, - "total_clicks": 32 - }, - { - "article_count": 1, - "avg_clicks": 96, - "ctg_id": 4, - "total_clicks": 96 - } - ] - }, - { - "lastQuery": "SELECT SUM(`article`.`click_num`) FROM `article` WHERE `state` =? ;", - "match_single_field": false, - "name": "Sum 求和 (table.column 格式)", - "result": true, - "sum": 0 - }, - { - "name": "聚合函数一致性验证", - "result": false, - "summary": "Sum: 12311=0, Avg: 1367.8889=0, Max: 9999=0, Min: 1=0" - }, - { - "lastQuery": "SELECT SUM(`article`.`click_num`) FROM `article` LEFT JOIN `ctg` ON `article`.`ctg_id` = `ctg`.`id` WHERE `article`.`state` =? ;", - "name": "Sum 带 JOIN (table.column 格式)", - "result": true, - "sum": 0 - }, - { - "count": 9, - "lastQuery": "SELECT COUNT(*) FROM `article` LEFT JOIN `ctg` ON `article`.`ctg_id` = `ctg`.`id` WHERE `article`.`state` =? ;", - "name": "Count 带 JOIN", - "result": true - } - ] - }, - "6_pagination": { - "name": "分页查询测试", - "success": true, - "tests": [ - { - "count": 5, - "name": "PageSelect 分页查询", - "result": true - }, - { - "count": 4, - "name": "PageSelect 第二页", - "result": true - }, - { - "count": 3, - "name": "链式 Page 分页", - "result": true - }, - { - "count": 3, - "lastQuery": "SELECT id,title FROM `article` WHERE (`state` =?) LIMIT 3 OFFSET 2 ;", - "name": "Offset 偏移查询", - "result": true - } - ] - }, - "7_batch_insert": { - "name": "批量插入测试", - "success": true, - "tests": [ - { - "affected": 3, - "lastQuery": "INSERT INTO `test_batch` (`name`, `state`, `title`) VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?)", - "name": "Inserts 批量插入", - "result": true - }, - { - "affected": 2, - "name": "Inserts 带 [#] 标记", - "result": true - } - ] - }, - "8_upsert": { - "name": "Upsert测试", - "success": true, - "tests": [ - { - "affected": 1, - "lastQuery": "INSERT INTO `admin` (`phone`, `state`, `password`, `role_id`, `title`, `create_time`, `modify_time`, `name`) VALUES (?, ?, ?, ?, ?, NOW(), NOW(), ?) ON DUPLICATE KEY UPDATE `name` = VALUES(`name`), `state` = VALUES(`state`), `title` = VALUES(`title`), `modify_time` = NOW()", - "name": "Upsert 插入新记录 (admin表)", - "result": true - }, - { - "affected": 2, - "name": "Upsert 更新已存在记录", - "result": true, - "updatedAdmin": { - "create_time": "2026-04-11 16:39:56", - "id": 41, - "modify_time": "2026-04-11 16:39:56", - "name": "Upsert更新后管理员", - "password": "test123", - "phone": "19975925594", - "role_id": 2, - "state": 1, - "title": "更新后职位" - } - } - ] - }, - "9_transaction": { - "name": "事务测试", - "success": true, - "tests": [ - { - "name": "事务成功提交", - "recordExists": true, - "result": true - }, - { - "name": "事务回滚", - "recordRolledBack": false, - "result": true - } - ] - } - }, - "status": 0 - }, - "expect": { - "result": { - "1_basic_crud": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample", - "result": true - } - ] - }, - "2_condition_syntax": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample", - "result": true - } - ] - }, - "3_chain_query": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample" - } - ] - }, - "4_join_query": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample" - } - ] - }, - "5_aggregate": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample" - } - ] - }, - "6_pagination": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample" - } - ] - }, - "7_batch_insert": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample" - } - ] - }, - "8_upsert": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample" - } - ] - }, - "9_transaction": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample" - } - ] - } - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "test", - "method": "GET", + "method": "POST", "params": [], "path": "/app/test/all", "project": "app", @@ -1854,47 +211,9 @@ "tested": true }, { - "cases": [ - { - "name": "批量插入", - "method": "GET", - "passed": true, - "response": { - "result": { - "name": "批量插入测试", - "success": true, - "tests": [ - { - "affected": 3, - "lastQuery": "INSERT INTO `test_batch` (`name`, `state`, `title`) VALUES (?, ?, ?), (?, ?, ?), (?, ?, ?)", - "name": "Inserts 批量插入", - "result": true - }, - { - "affected": 2, - "name": "Inserts 带 [#] 标记", - "result": true - } - ] - }, - "status": 0 - }, - "expect": { - "result": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample" - } - ] - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "test", - "method": "GET", + "method": "POST", "params": [], "path": "/app/test/batch", "project": "app", @@ -1902,107 +221,9 @@ "tested": true }, { - "cases": [ - { - "name": "链式查询", - "method": "GET", - "passed": true, - "response": { - "result": { - "name": "链式查询测试", - "success": true, - "tests": [ - { - "count": 9, - "name": "基本链式查询 Table().Where().Select()", - "result": true - }, - { - "count": 9, - "name": "链式 And 条件", - "result": true - }, - { - "count": 9, - "name": "链式 Or 条件", - "result": true - }, - { - "count": 5, - "name": "链式 Order 排序", - "result": true - }, - { - "count": 3, - "name": "链式 Limit 限制", - "result": true - }, - { - "article": { - "author": "管理员", - "id": 1, - "title": "数据库入门指南" - }, - "name": "链式 Get 获取单条", - "result": true - }, - { - "count": 9, - "name": "链式 Count 统计", - "result": true - }, - { - "count": 5, - "name": "链式 Page 分页", - "result": true - }, - { - "name": "链式 Group 分组", - "result": true, - "stats": [ - { - "cnt": 3, - "ctg_id": 1 - }, - { - "cnt": 4, - "ctg_id": 2 - }, - { - "cnt": 1, - "ctg_id": 3 - }, - { - "cnt": 1, - "ctg_id": 4 - } - ] - }, - { - "affected": 1, - "name": "链式 Update 更新", - "result": true - } - ] - }, - "status": 0 - }, - "expect": { - "result": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample" - } - ] - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "test", - "method": "GET", + "method": "POST", "params": [], "path": "/app/test/chain", "project": "app", @@ -2010,123 +231,9 @@ "tested": true }, { - "cases": [ - { - "name": "条件查询", - "method": "GET", - "passed": true, - "response": { - "result": { - "name": "条件查询语法测试", - "success": true, - "tests": [ - { - "count": 3, - "name": "等于条件 (=)", - "result": true - }, - { - "count": 3, - "lastQuery": "SELECT id,title,state FROM `article` WHERE `state` !=? LIMIT 3 ;", - "name": "不等于条件 ([!])", - "result": true - }, - { - "count": 3, - "name": "大于小于条件 ([\u003e], [\u003c])", - "result": true - }, - { - "count": 3, - "name": "大于等于小于等于条件 ([\u003e=], [\u003c=])", - "result": true - }, - { - "count": 1, - "lastQuery": "SELECT id,title FROM `article` WHERE `title` LIKE ? LIMIT 3 ;", - "name": "LIKE 模糊查询 ([~])", - "result": true - }, - { - "count": 0, - "name": "右模糊查询 ([~!])", - "result": true - }, - { - "count": 3, - "lastQuery": "SELECT id,title,click_num FROM `article` WHERE `click_num` BETWEEN ? AND ? LIMIT 3 ;", - "name": "BETWEEN 区间查询 ([\u003c\u003e])", - "result": true - }, - { - "count": 3, - "name": "NOT BETWEEN 查询 ([\u003e\u003c])", - "result": true - }, - { - "count": 5, - "lastQuery": "SELECT id,title FROM `article` WHERE (`id` BETWEEN ? AND ? ) LIMIT 5 ;", - "name": "IN 查询", - "result": true - }, - { - "count": 5, - "name": "NOT IN 查询 ([!])", - "result": true - }, - { - "count": 3, - "name": "IS NULL 查询", - "result": true - }, - { - "count": 3, - "name": "IS NOT NULL 查询 ([!])", - "result": true - }, - { - "count": 3, - "lastQuery": "SELECT id,title,create_time FROM `article` WHERE create_time \u003e DATE_SUB(NOW(), INTERVAL 365 DAY) LIMIT 3 ;", - "name": "直接 SQL 片段查询 ([##])", - "result": true - }, - { - "count": 3, - "name": "显式 AND 条件", - "result": true - }, - { - "count": 5, - "name": "OR 条件", - "result": true - }, - { - "count": 5, - "lastQuery": "SELECT id,title,sort,state FROM `article` WHERE (( `click_num` \u003e? OR `sort` \u003e=? ) AND `state` =?) LIMIT 5 ;", - "name": "嵌套 AND/OR 条件", - "result": true - } - ] - }, - "status": 0 - }, - "expect": { - "result": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample", - "result": true - } - ] - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "test", - "method": "GET", + "method": "POST", "params": [], "path": "/app/test/condition", "project": "app", @@ -2134,79 +241,9 @@ "tested": true }, { - "cases": [ - { - "name": "CRUD测试", - "method": "GET", - "passed": true, - "response": { - "result": { - "name": "基础CRUD测试", - "success": true, - "tests": [ - { - "adminId": 45, - "lastQuery": "INSERT INTO `admin` (`password`,`role_id`,`title`,`create_time`,`modify_time`,`name`,`phone`,`state`) VALUES (?,?,?,NOW(),NOW(),?,?,?);", - "name": "Insert 插入测试 (admin表)", - "result": true - }, - { - "admin": { - "create_time": "2026-04-11 16:40:03", - "id": 45, - "modify_time": "2026-04-11 16:40:03", - "name": "测试管理员_1775925600", - "password": "test123456", - "phone": "13875925600", - "role_id": 1, - "state": 1, - "title": "测试职位" - }, - "name": "Get 获取单条记录测试", - "result": true - }, - { - "count": 5, - "name": "Select 单条件查询测试", - "result": true - }, - { - "count": 5, - "lastQuery": "SELECT * FROM `admin` WHERE `role_id` \u003e? AND `state` =? ORDER BY id DESC LIMIT 5 ;", - "name": "Select 多条件自动AND测试", - "result": true - }, - { - "affected": 1, - "name": "Update 更新测试", - "result": true - }, - { - "affected": 1, - "name": "Delete 删除测试", - "result": true - } - ] - }, - "status": 0 - }, - "expect": { - "result": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample", - "result": true - } - ] - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "test", - "method": "GET", + "method": "POST", "params": [], "path": "/app/test/crud", "project": "app", @@ -2214,116 +251,9 @@ "tested": true }, { - "cases": [ - { - "name": "JOIN查询", - "method": "GET", - "passed": true, - "response": { - "result": { - "name": "JOIN查询测试", - "success": true, - "tests": [ - { - "count": 5, - "data": [ - { - "ctg_name": "新闻资讯", - "id": 1, - "title": "数据库入门指南" - }, - { - "ctg_name": "新闻资讯", - "id": 2, - "title": "新闻发布系统上线公告" - }, - { - "ctg_name": "新闻资讯", - "id": 11, - "title": "高点击量文章" - }, - { - "ctg_name": "技术文档", - "id": 3, - "title": "Go语言最佳实践" - }, - { - "ctg_name": "技术文档", - "id": 4, - "title": "API接口设计规范" - } - ], - "name": "LEFT JOIN 链式查询", - "result": true - }, - { - "count": 5, - "lastQuery": "SELECT `article`.`id`, `article`.`title`, `ctg`.`name` as ctg_name FROM `article` LEFT JOIN `ctg` ON `article`.`ctg_id` = `ctg`.`id` WHERE `article`.`state` =? LIMIT 5 ;", - "name": "传统 JOIN 语法", - "result": true - }, - { - "count": 5, - "data": [ - { - "admin_name": "超级管理员", - "ctg_name": "新闻资讯", - "id": 1, - "title": "数据库入门指南" - }, - { - "admin_name": "编辑员", - "ctg_name": "新闻资讯", - "id": 2, - "title": "新闻发布系统上线公告" - }, - { - "admin_name": "编辑员", - "ctg_name": "新闻资讯", - "id": 11, - "title": "高点击量文章" - }, - { - "admin_name": "超级管理员", - "ctg_name": "技术文档", - "id": 3, - "title": "Go语言最佳实践" - }, - { - "admin_name": "审核员", - "ctg_name": "技术文档", - "id": 4, - "title": "API接口设计规范" - } - ], - "name": "多表 JOIN", - "result": true - }, - { - "count": 5, - "name": "INNER JOIN", - "result": true - } - ] - }, - "status": 0 - }, - "expect": { - "result": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample" - } - ] - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "test", - "method": "GET", + "method": "POST", "params": [], "path": "/app/test/join", "project": "app", @@ -2331,57 +261,9 @@ "tested": true }, { - "cases": [ - { - "name": "分页查询", - "method": "GET", - "passed": true, - "response": { - "result": { - "name": "分页查询测试", - "success": true, - "tests": [ - { - "count": 5, - "name": "PageSelect 分页查询", - "result": true - }, - { - "count": 4, - "name": "PageSelect 第二页", - "result": true - }, - { - "count": 3, - "name": "链式 Page 分页", - "result": true - }, - { - "count": 3, - "lastQuery": "SELECT id,title FROM `article` WHERE (`state` =?) LIMIT 3 OFFSET 2 ;", - "name": "Offset 偏移查询", - "result": true - } - ] - }, - "status": 0 - }, - "expect": { - "result": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample" - } - ] - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "test", - "method": "GET", + "method": "POST", "params": [], "path": "/app/test/pagination", "project": "app", @@ -2389,37 +271,9 @@ "tested": true }, { - "cases": [ - { - "name": "固定返回错误码2", - "method": "GET", - "passed": true, - "response": { - "error": { - "msg": "dsadasd", - "type": "访问权限异常" - }, - "result": { - "msg": "dsadasd", - "type": "访问权限异常" - }, - "status": 2 - }, - "expect": { - "error": { - "msg": "dsadasd", - "type": "访问权限异常" - }, - "result": { - "msg": "dsadasd", - "type": "访问权限异常" - }, - "status": 2 - } - } - ], + "cases": null, "ctr": "test", - "method": "GET", + "method": "POST", "params": [], "path": "/app/test/test", "project": "app", @@ -2427,46 +281,9 @@ "tested": true }, { - "cases": [ - { - "name": "事务测试", - "method": "GET", - "passed": true, - "response": { - "result": { - "name": "事务测试", - "success": true, - "tests": [ - { - "name": "事务成功提交", - "recordExists": true, - "result": true - }, - { - "name": "事务回滚", - "recordRolledBack": false, - "result": true - } - ] - }, - "status": 0 - }, - "expect": { - "result": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample" - } - ] - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "test", - "method": "GET", + "method": "POST", "params": [], "path": "/app/test/transaction", "project": "app", @@ -2474,58 +291,9 @@ "tested": true }, { - "cases": [ - { - "name": "Upsert测试", - "method": "GET", - "passed": true, - "response": { - "result": { - "name": "Upsert测试", - "success": true, - "tests": [ - { - "affected": 1, - "lastQuery": "INSERT INTO `admin` (`title`, `create_time`, `modify_time`, `name`, `phone`, `state`, `password`, `role_id`) VALUES (?, NOW(), NOW(), ?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE `name` = VALUES(`name`), `state` = VALUES(`state`), `title` = VALUES(`title`), `modify_time` = NOW()", - "name": "Upsert 插入新记录 (admin表)", - "result": true - }, - { - "affected": 2, - "name": "Upsert 更新已存在记录", - "result": true, - "updatedAdmin": { - "create_time": "2026-04-11 16:39:57", - "id": 43, - "modify_time": "2026-04-11 16:39:58", - "name": "Upsert更新后管理员", - "password": "test123", - "phone": "19975925595", - "role_id": 2, - "state": 1, - "title": "更新后职位" - } - } - ] - }, - "status": 0 - }, - "expect": { - "result": { - "name": "sample", - "success": true, - "tests": [ - { - "name": "sample" - } - ] - }, - "status": 0 - } - } - ], + "cases": null, "ctr": "test", - "method": "GET", + "method": "POST", "params": [], "path": "/app/test/upsert", "project": "app", diff --git a/example/tpt/swagger/app/index.html b/example/tpt/swagger/app/index.html index b219829..85bd93a 100644 --- a/example/tpt/swagger/app/index.html +++ b/example/tpt/swagger/app/index.html @@ -1,7 +1,7 @@