con un clic
testing-patterns
Table-driven tests, -race flag, stub patterns
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Menú
Table-driven tests, -race flag, stub patterns
Instalar con Codex o Claude Copia este prompt, pégalo en Codex, Claude u otro asistente, y deja que revise la página de la skill y la instale por ti.
Basado en la clasificación ocupacional SOC
| name | testing-patterns |
| description | Table-driven tests, -race flag, stub patterns |
| domain | quality |
| confidence | high |
| source | hyoka/internal/*_test.go files |
Hyoka test suite follows Go idioms: table-driven tests for comprehensive coverage, -race flag for detecting concurrency issues, and stub patterns for mocking external dependencies (Copilot SDK, file system).
Use table-driven tests to test multiple scenarios with the same logic:
✓ Correct:
func TestBehaviorGrader_ConstraintValidation(t *testing.T) {
tests := []struct {
name string
config map[string]any
actionLog []ActionEvent
expect bool
wantErr string
}{
{
name: "required tools present",
config: map[string]any{
"required_tools": []any{"read_file", "edit_file"},
},
actionLog: []ActionEvent{
{Tool: "read_file", TurnNumber: 1},
{Tool: "edit_file", TurnNumber: 2},
},
expect: true,
},
{
name: "required tool missing",
config: map[string]any{
"required_tools": []any{"read_file"},
},
actionLog: []ActionEvent{
{Tool: "bash", TurnNumber: 1},
},
expect: false,
wantErr: "required tool not found",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g, _ := NewBehaviorGrader("test", tt.config)
result, err := g.Grade(context.Background(), GraderInput{
ActionLog: tt.actionLog,
})
if (err != nil) != (tt.wantErr != "") {
t.Fatalf("unexpected error: %v", err)
}
if result.Pass != tt.expect {
t.Errorf("expected Pass=%v, got %v", tt.expect, result.Pass)
}
})
}
}
Always run tests with -race flag:
go test -race ./hyoka/...
The -race detector catches unsynchronized access to shared memory in concurrent code. This is critical for:
When testing engine behavior without real graders:
type StubGrader struct {
gradeFn func(context.Context, GraderInput) (GraderResult, error)
}
func (sg *StubGrader) Grade(ctx context.Context, input GraderInput) (GraderResult, error) {
return sg.gradeFn(ctx, input)
}
// Usage in test
stubGrader := &StubGrader{
gradeFn: func(_ context.Context, _ GraderInput) (GraderResult, error) {
return GraderResult{Pass: true, Score: 1.0}, nil
},
}
Mock file operations without touching disk:
type stubFileReader struct {
readFn func(path string) (string, error)
}
func (s *stubFileReader) Read(path string) (string, error) {
return s.readFn(path)
}
// Usage
stubFS := &stubFileReader{
readFn: func(path string) (string, error) {
if path == "/test/main.py" {
return "# Generated code", nil
}
return "", os.ErrNotExist
},
}
*_test.go in same package)*_integration_test.go)testdata/ directory for test files# All tests
go test ./hyoka/...
# With race detector
go test -race ./hyoka/...
# Specific test
go test -run TestBehaviorGrader ./hyoka/internal/graders
# Verbose with coverage
go test -v -cover ./hyoka/...
-race failures (concurrency bugs are subtle)hyoka/internal/graders/*_test.gohyoka/internal/eval/*_test.gohyoka/testdata/How to write comprehensive architectural proposals that drive alignment before code is written
How the eval engine works: generate → grade → review → report
Record final outcomes to history.md, not intermediate requests or reversed decisions
Tone enforcement patterns for external-facing community responses
Team initialization flow (Phase 1 proposal + Phase 2 creation)
Core conventions and patterns for this codebase