必须先完整接收多返回值再分步校验:先用 require.noerror(t, err) 确保无错,再用 assert.equal(t, want, got) 比较结果;避免一行断言导致 panic 掩盖问题,提升调试效率。

用 assert.NoError + assert.Equal 分开校验多返回值
Go 函数常返回 value, error,不能把断言写成一行,否则 error 为非 nil 时后续逻辑可能 panic 或掩盖真实问题。必须先完整接收,再分步校验。
常见错误是:assert.Equal(t, 42, riskyFunc())——如果 riskyFunc() panic 或返回 err != nil,assert 根本不会执行,测试直接崩溃,还看不到失败上下文。
- 正确做法:先接收所有返回值,再用
require.NoError(t, err)检查前置条件,确保后续断言有意义 - 业务结果用
assert.Equal(t, want, got),即使失败也继续跑,方便一次看到多个字段偏差 - 对浮点数别用
Equal,改用assert.InDelta(t, got, want, 1e-6) - 结构体或 map 比较推荐用
assert.JSONEq(序列化后比字符串),避开reflect.DeepEqual对指针、nil 切片等的敏感行为
避免 assert.Equal 在类型不匹配时误报
assert.Equal 底层依赖 reflect.DeepEqual,但 Go 类型系统严格,容易在看似相等的地方失败。
比如:int(42) 和 int64(42) 直接 Equal 会失败;[]string(nil) 和 []string{} 默认判为不等;&T{X: 1} 和 &T{X: 1} 因地址不同也被认为不等。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
- 跨类型比较优先用
assert.EqualValues(忽略底层类型,只比值) - 切片长度不确定时,先
require.Len(t, items, 3),再逐项assert.Equal或用assert.ElementsMatch忽略顺序 - 自定义 error 实例不等于
nil即使Error()返回空字符串,要用assert.ErrorContains(t, err, "timeout")而非assert.Equal(t, "timeout", err.Error())
require.NoError 应该用在 setup 阶段,不是每个返回值都 require
require 不是“更强的 assert”,它是带 t.Fatal 的断言,失败即终止当前测试函数。滥用会导致你错过关键信息。
典型误用:对每个业务返回值都写 require.Equal,结果第一个字段错就停了,后面几个字段是否符合预期完全看不到。
- 只对 setup、初始化、依赖调用(如 DB 连接、HTTP client 构建、JSON 解码)用
require - 对 handler 响应体解析:
require.NoError(t, json.Unmarshal(rr.Body.Bytes(), &resp))是合理前置,之后再assert.Equal(t, "success", resp["status"]) - 别在
defer中调用require——panic 会被 recover,require失效 - 如果 cleanup 逻辑依赖资源已成功创建,得确保它不被
require的提前退出绕过
表驱动测试中嵌入 assert / require 要注意求值顺序
表格驱动测试里,容易把待测函数调用和断言写在同一行,尤其在循环中,一旦某次迭代 panic,整个测试就中断,无法定位是第几个 case 出的问题。
例如:assert.Equal(t, tc.want, calc(tc.input)) 中 calc() 若 panic,assert 不执行,t 也不报具体 case 编号。
- 务必拆成两步:
got := calc(tc.input)→assert.Equal(t, tc.want, got) - 若
calc()可能 panic,加defer func() { if r := recover(); r != nil { t.Fatalf("panic in case %v: %v", tc.name, r) } }() - 每个 case 的
name字段要唯一且可读,失败日志才能快速对应到数据行 - 错误消息里带上
tc.name:assert.Equal(t, tc.want, got, "case %s failed", tc.name)
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










