Go TDD 命令¶
此命令使用惯用的 Go 测试模式,在 Go 代码中强制执行测试驱动开发方法论。
此命令的功能¶
- 类型/接口定义:先搭建函数签名框架
- 编写表驱动测试:生成全面的测试用例(RED)
- 运行测试:验证测试因正确原因而失败
- 实现代码:编写通过测试所需的最少代码(GREEN)
- 重构:在保持测试通过的同时改进代码
- 检查覆盖率:确保覆盖率不低于 80%
使用时机¶
应在以下情况使用 /go-test:
- 实现新的 Go 函数
- 为现有代码添加测试覆盖率
- 修复 Bug(先编写失败的测试)
- 实现核心业务逻辑
- 学习 Go 中的 TDD 工作流程
TDD 周期¶
RED → 실패하는 테이블 기반 테스트 작성
GREEN → 통과하기 위한 최소한의 코드 구현
REFACTOR → 코드 개선, 테스트는 통과 유지
REPEAT → 다음 테스트 케이스
示例会话¶
User: /go-test 이메일 주소를 검증하는 함수가 필요합니다
Agent:
# TDD 세션: 이메일 검증기
## 1단계: 인터페이스 정의
```go
// validator/email.go
package validator
// ValidateEmail은 주어진 문자열이 유효한 이메일 주소인지 확인합니다.
// 유효하면 nil을 반환하고, 그렇지 않으면 이슈를 설명하는 error를 반환합니다.
func ValidateEmail(email string) error {
panic("not implemented")
}
```
## 2단계: 테이블 기반 테스트 작성 (RED)
```go
// validator/email_test.go
package validator
import (
"testing"
)
func TestValidateEmail(t *testing.T) {
tests := []struct {
name string
email string
wantErr bool
}{
// 유효한 이메일
{"단순 이메일", "user@example.com", false},
{"서브도메인 포함", "user@mail.example.com", false},
{"플러스 포함", "user+tag@example.com", false},
{"점 포함", "first.last@example.com", false},
// 유효하지 않은 이메일
{"빈 문자열", "", true},
{"@ 기호 없음", "userexample.com", true},
{"도메인 없음", "user@", true},
{"로컬 파트 없음", "@example.com", true},
{"이중 @", "user@@example.com", true},
{"공백 포함", "user @example.com", true},
{"TLD 없음", "user@example", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := ValidateEmail(tt.email)
if tt.wantErr && err == nil {
t.Errorf("ValidateEmail(%q) = nil; want error", tt.email)
}
if !tt.wantErr && err != nil {
t.Errorf("ValidateEmail(%q) = %v; want nil", tt.email, err)
}
})
}
}
```
## 3단계: 테스트 실행 - 실패 확인
```bash
$ go test ./validator/...
--- FAIL: TestValidateEmail (0.00s)
--- FAIL: TestValidateEmail/단순_이메일 (0.00s)
panic: not implemented
FAIL
```
✓ 예상대로 테스트 실패 (panic).
## 4단계: 최소한의 코드 구현 (GREEN)
```go
// validator/email.go
package validator
import (
"errors"
"regexp"
)
var emailRegex = regexp.MustCompile(`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`)
var (
ErrEmailEmpty = errors.New("email cannot be empty")
ErrEmailInvalid = errors.New("email format is invalid")
)
func ValidateEmail(email string) error {
if email == "" {
return ErrEmailEmpty
}
if !emailRegex.MatchString(email) {
return ErrEmailInvalid
}
return nil
}
```
## 5단계: 테스트 실행 - 통과 확인
```bash
$ go test ./validator/...
PASS
ok project/validator 0.003s
```
✓ 모든 테스트 통과!
## 6단계: 커버리지 확인
```bash
$ go test -cover ./validator/...
PASS
coverage: 100.0% of statements
ok project/validator 0.003s
```
✓ 커버리지: 100%
## TDD 완료!
测试模式¶
表驱动测试¶
tests := []struct {
name string
input InputType
want OutputType
wantErr bool
}{
{"케이스 1", input1, want1, false},
{"케이스 2", input2, want2, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Function(tt.input)
// 단언문
})
}
并行测试¶
for _, tt := range tests {
tt := tt // 캡처
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
// 테스트 본문
})
}
测试辅助函数¶
func setupTestDB(t *testing.T) *sql.DB {
t.Helper()
db := createDB()
t.Cleanup(func() { db.Close() })
return db
}
覆盖率命令¶
# 기본 커버리지
go test -cover ./...
# 커버리지 프로파일
go test -coverprofile=coverage.out ./...
# 브라우저에서 확인
go tool cover -html=coverage.out
# 함수별 커버리지
go tool cover -func=coverage.out
# 레이스 감지와 함께
go test -race -cover ./...
覆盖率目标¶
| 代码类型 | 目标 |
|---|---|
| 核心业务逻辑 | 100% |
| 公开 API | 90%+ |
| 常规代码 | 80%+ |
| 生成的代码 | 排除 |
TDD 最佳实践¶
应该做的:
- 在实现之前先编写测试
- 每次更改后运行测试
- 使用表驱动测试以获得全面覆盖率
- 测试行为而非实现细节
- 包含边界情况(空值、nil、最大值)
不应该做的:
- 在编写测试之前先写实现
- 跳过 RED 阶段
- 直接测试私有函数
- 在测试中使用
time.Sleep - 忽略不稳定的测试
相关命令¶
/go-build- 修复构建错误/go-review- 实现后的代码审查/verify- 完整验证循环
相关条目¶
- 技能:
skills/golang-testing/ - 技能:
skills/tdd-workflow/
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 ev/ECC