Files
hotime/example/app/app_test.go
T
hoteas 16496a8dc0 feat(testing): Flows/FromCase、增量 swagger 与 Doc-Driven 门禁
补齐多接口流程联调与控制台体验,并落地仓内 Doc-Driven+TDD 总规则与文档。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-13 18:11:08 +08:00

112 lines
2.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package app
import (
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"
. "code.hoteas.com/golang/hotime"
)
var ProjectTest = ProjTest{
"test": TestTest,
"mysql": MysqlTest,
"dmdb": DmdbTest,
"cache": CacheTest,
"expect_demo": ExpectDemoTest,
}
var testApp *TestApp
func TestMain(m *testing.M) {
testApp = Test("config/config.json").
WorkDir("..").
Swagger("My API", "1.0.0").
Proj(TestProj{
"app": {
Proj: Project,
Tests: ProjectTest,
},
}).
Flows(DemoFlows)
// 仅本 example:空库时灌演示数据。须连专用测试库,勿对生产库调用。
SetupDatabase(&testApp.Db)
os.Exit(testApp.Run(m))
}
func TestApi(t *testing.T) {
testApp.RunTests(t)
}
// TestInterruptStop 模拟提前中断:string_result 跑完后 RequestStopzzz_should_skip 应 Skip
// swagger 中 string_result 的 cases 应保留。注意:TestMain 已 Chdir 到 example/,此处不再 WorkDir。
func TestInterruptStop(t *testing.T) {
var app *TestApp
secondRan := false
app = Test("config/config.json").
Swagger("Interrupt Demo", "1.0.0").
Proj(TestProj{
"app": {
Proj: Project,
Tests: ProjTest{
"expect_demo": CtrTest{
"string_result": {Desc: "先跑并停测", Func: func(a *Api) {
ExpectDemoTest["string_result"].Func(a)
app.RequestStop()
}},
"zzz_should_skip": {Desc: "应被跳过", Func: func(a *Api) {
secondRan = true
t.Error("zzz_should_skip 在 RequestStop 后不应执行")
}},
},
},
},
})
SetupDatabase(&app.Db)
app.RunTests(t)
if secondRan {
t.Fatal("停测后仍执行了后续接口")
}
_ = app.Db.RollbackTestTx()
// 收尾写盘(中断路径下可能未跑满 GenerateSwagger,显式补一次增量合并)
if err := app.GenerateSwagger("Interrupt Demo", "1.0.0", app.Config.GetString("tpt")); err != nil {
t.Fatalf("GenerateSwagger: %v", err)
}
specPath := filepath.Join(app.Config.GetString("tpt"), "swagger", "app", "api-spec.json")
data, err := os.ReadFile(specPath)
if err != nil {
t.Fatalf("应已生成 swagger %s: %v", specPath, err)
}
var spec struct {
Endpoints []struct {
Path string `json:"path"`
Cases json.RawMessage `json:"cases"`
} `json:"endpoints"`
}
if err := json.Unmarshal(data, &spec); err != nil {
t.Fatalf("解析 api-spec 失败: %v", err)
}
found := false
for _, ep := range spec.Endpoints {
if ep.Path != "/app/expect_demo/string_result" {
continue
}
found = true
if !strings.Contains(string(ep.Cases), `"name"`) {
t.Fatalf("string_result 应保留测试 cases,实际: %s", string(ep.Cases))
}
}
if !found {
t.Fatal("swagger 中应包含已跑完的 /app/expect_demo/string_result")
}
}