根本原因是未调用RunSpecs:每个_test.go文件必须有且仅有一个func TestXxx(t *testing.T),其中先RegisterFailHandler(Fail),再唯一调用RunSpecs(t, "Suite Name");Describe/It必须包裹在此函数内,否则panic“no tests registered”。

为什么 Ginkgo 测试一跑就 panic
根本原因:没调用 RunSpecs。Ginkgo 不是靠 go test 自动发现测试的,它需要显式启动运行时注册机制。
-
go test输出ok ./pkg 0.001s但零断言执行,或直接 panic 报no tests to run,基本都是这个原因 - 每个
_test.go文件必须有且仅有一个func TestXxx(t *testing.T)入口函数 - 该函数内必须先调用
RegisterFailHandler(Fail),再唯一调用RunSpecs(t, "Suite Name") - 不能把
RunSpecs放在init()或包级变量初始化里——会破坏go test生命周期
Describe 和 It 必须写在哪
Describe 和 It 不能直接写在包顶层,否则 panic:failed to run spec: no tests registered。
- 它们必须包裹在
func TestXxx(t *testing.T)函数体内(可以是同一个文件,也可以是其他_test.go文件) - Ginkgo 靠
RunSpecs扫描当前测试函数作用域内注册的 spec 树,顶层声明无法被识别 - 常见错误:把
var _ = Describe(...)写在文件顶部、没包进TestXxx,结果测试“静默失败”
Gomega 断言失败却不显示具体值
不是 Gomega 本身的问题,而是 RegisterFailHandler 没配对或配错。
-
Fail来自github.com/onsi/ginkgo/v2,不是t.Fail;写成RegisterFailHandler(t.Fail)会 panic - 必须在
RunSpecs之前调用RegisterFailHandler(Fail),否则Expect(...).To(Equal(x))失败时只抛空 panic 或 “test timed out” - 如果用
ginkgo run命令,Fail默认已注册;但混用go test时这步绝不能省
并发测试下 BeforeSuite 和 BeforeEach 混用导致随机失败
并行运行(ginkgo -p)时,资源生命周期错配是高频坑点。
立即学习“go语言免费学习笔记(深入)”;
-
BeforeSuite只执行一次,适合初始化 DB 连接池、httptest.NewServer、全局配置——但必须线程安全或带锁访问 -
BeforeEach每个It前都执行,适合新建map、临时文件、mock 对象等独占资源 - 典型症状:单测全过,加
-p 4后随机报connection refused或key already exists - 绝对避免在
BeforeSuite里赋值可变全局变量(如var db *sql.DB),然后在It里改它的状态
RunSpecs 的位置、Fail 的来源、BeforeSuite 的并发边界——这些地方错一点,测试就变成黑盒。



















