mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 22:06:38 +08:00
3.2 KiB
3.2 KiB
可扩展验证 API
设计可重用测试验证函数的详细参考,调用者可以将其用于验收测试。来源:Google Go Style Guide(最佳实践)。
*test 包导出模式
当你拥有一个由他人实现的接口时,在配套的 *test 包中导出一个验证函数。这使实现者无需复制你的测试逻辑即可验证正确性。
// Package storagetest 为 storage.Backend 提供验收测试。
package storagetest
// Verify 对任何 storage.Backend 运行验证套件。
// 返回描述第一个违规行为的错误,成功时返回 nil。
func Verify(b storage.Backend) error {
if err := verifyRoundTrip(b); err != nil {
return fmt.Errorf("round-trip: %w", err)
}
if err := verifyNotFound(b); err != nil {
return fmt.Errorf("not-found: %w", err)
}
return nil
}
调用者编写一个薄测试来接入他们的实现:
func TestMyBackend(t *testing.T) {
b := mybackend.New(t)
if err := storagetest.Verify(b); err != nil {
t.Errorf("MyBackend failed acceptance: %v", err)
}
}
设计可扩展的验证函数
返回错误,而非 *testing.T 失败。 这使验证函数可作为普通 Go 函数使用 — 调用者决定违规是 t.Error 还是 t.Fatal。
// 好:返回错误 — 调用者控制测试流程
func ExercisePlayer(b *chess.Board, p chess.Player) error {
move := p.Move()
if putsOwnKingIntoCheck(b, move) {
return &IllegalMoveError{Move: move, Reason: "puts own king in check"}
}
return nil
}
// 不好:调用 t.Fatal — 调用者失去控制
func ExercisePlayer(t *testing.T, b *chess.Board, p chess.Player) {
t.Helper()
move := p.Move()
if putsOwnKingIntoCheck(b, move) {
t.Fatalf("illegal move: %v puts own king in check", move)
}
}
在需要丰富诊断信息时使用自定义错误类型:
type IllegalMoveError struct {
Move chess.Move
Reason string
}
func (e *IllegalMoveError) Error() string {
return fmt.Sprintf("illegal move %v: %s", e.Move, e.Reason)
}
何时使用验证 API vs 简单辅助函数
| 场景 | 使用方式 |
|---|---|
| 你拥有的接口,由他人实现 | *test 包中的验证 API |
| 同一包中跨测试共享设置 | 使用 t.Helper() 的测试辅助函数 |
| 在 2-3 个测试中重用的复杂断言 | 返回 error 或 bool 的辅助函数 |
| 一次性的设置或比较 | 内联测试代码 |
验证 API 在以下场景值得额外的包:
- 多个外部包将实现你的接口
- 契约有容易被忽略的非显而易见的不变量
- 你想为"正确行为"提供单一事实来源
简单辅助函数 在以下场景更好:
- 辅助函数是直接的设置或比较函数
- 重用是偶然的,不是已发布契约的一部分
命名约定
使用表示范围的动词命名函数:Verify、Exercise、RunConformance。接受被测接口作为参数 — 绝不在验证包内部构造实现。
| 包 | 函数 | 用途 |
|---|---|---|
storagetest |
Verify |
验证 storage.Backend |
chesstest |
ExercisePlayer |
验证 chess.Player |
cachetest |
RunConformance |
cache.Cache 的完整一致性套件 |