com um clique
write-tests
Write Go unit and e2e tests following Theatrum's exact conventions
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Menu
Write Go unit and e2e tests following Theatrum's exact conventions
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Baseado na classificação ocupacional SOC
Update CLAUDE.md and README.md to reflect code changes
Audit the codebase for hexagonal architecture violations (forbidden imports, dependency direction, port conformance)
Explain Theatrum's hexagonal (ports & adapters) architecture with concrete examples from the codebase
Expert reference on streaming protocols (HLS, DASH, RTMP, adaptive bitrate) grounded in Theatrum's implementation
Boot the app, stream via RTMP, watch via HLS/DASH, and validate the full pipeline
Manage and extend the CI/CD pipeline (GitHub Actions, Docker, build scripts)
| name | write-tests |
| description | Write Go unit and e2e tests following Theatrum's exact conventions |
You write Go tests for Theatrum following the project's exact conventions. When invoked, write tests for the file or package specified in $ARGUMENTS. If no argument is given, ask what to test.
Before writing any test, read these reference files to match the project's style:
src/domain/services/pathTemplateService_test.go — Table-driven tests, subtests, error cases (most comprehensive)src/domain/services/viewerTracker_test.go — Mock storage, time-dependent behavior, helper constructorssrc/adapters/driven/metrics/viewerCollector_test.go — Prometheus testutil usagesrc/adapters/driven/ffmpegEncoder/repositories/ffmpegEncoder_test.go — DryRun mode testingAlso read the file under test and any port interfaces it depends on.
Read the file specified in $ARGUMENTS and understand:
testing package ONLYassert, no require, no suite)testing/fstest or other non-standard test helpers_test external package){originalFileName}_test.goTheatrum (e.g., import "Theatrum/domain/models")t.Run(tt.name, ...):func TestFunctionName_Behavior(t *testing.T) {
tests := []struct {
name string
input string
expected string
wantErr bool
}{
{
name: "descriptive case name",
input: "value",
expected: "result",
},
{
name: "error case description",
input: "bad",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result, err := FunctionUnderTest(tt.input)
if tt.wantErr {
if err == nil {
t.Fatalf("expected error, got nil")
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if result != tt.expected {
t.Errorf("got %q, want %q", result, tt.expected)
}
})
}
}
t.Errorf() for non-fatal assertions (test continues)t.Fatalf() for fatal assertions (test stops)t.Errorf("got %v, want %v", got, want)viewerTracker_test.go:type mockStorage struct{}
func (m *mockStorage) ReadFile(path string) ([]byte, error) { return nil, nil }
func (m *mockStorage) WriteFile(path string, data []byte) error { return nil }
func (m *mockStorage) DeleteFile(path string) error { return nil }
func (m *mockStorage) ListFiles(pattern string) ([]string, error) { return nil, nil }
func (m *mockStorage) GetFileSize(path string) (int64, error) { return 0, nil }
func (m *mockStorage) SearchFiles(pattern string, extensions []string) ([]string, []map[string]string, error) {
return nil, nil, nil
}
For mocks that need configurable behavior, use function fields:
type mockStorageWithBehavior struct {
readFileFunc func(path string) ([]byte, error)
writeFileFunc func(path string, data []byte) error
// ... other methods
}
func (m *mockStorageWithBehavior) ReadFile(path string) ([]byte, error) {
if m.readFileFunc != nil {
return m.readFileFunc(path)
}
return nil, nil
}
StoragePort (src/domain/repositories/storagePort.go):
type StoragePort interface {
ReadFile(path string) ([]byte, error)
WriteFile(path string, data []byte) error
DeleteFile(path string) error
ListFiles(pattern string) ([]string, error)
GetFileSize(path string) (int64, error)
SearchFiles(pattern string, extensions []string) ([]string, []map[string]string, error)
}
EncoderPort (src/domain/repositories/encoderPort.go):
type EncoderPort interface {
EncodeVideo(inputPath string, outputPath string, qualities map[string]models.Quality, distribution models.Distribution) error
}
Note: models.Distribution uses pointer fields (*Hls, *Dash). In tests, construct as:
dist := models.Distribution{Hls: &models.Hls{SegmentDuration: 6}}
dist := models.Distribution{Dash: &models.Dash{SegmentDuration: 6}}
dist := models.Distribution{Hls: &models.Hls{SegmentDuration: 2}, Dash: &models.Dash{SegmentDuration: 2}} // dual
ConfigurationPort (src/domain/repositories/configurationPort.go):
type ConfigurationPort interface {
Load(configPath string) (*models.Application, *models.Server, *map[string]models.Stream, error)
}
When a struct's New*() constructor starts goroutines or has side effects, create a test helper that directly initializes the struct:
// newTestTracker creates a ViewerTracker without starting the cleanup goroutine.
func newTestTracker() *ViewerTracker {
return &ViewerTracker{
streams: make(map[string]*streamTracking),
storage: &mockStorage{},
}
}
Priority order:
After writing tests, run them:
cd src && go test ./... -v -run TestNamePattern
For a specific package:
cd src && go test ./domain/services/ -v -run TestFunctionName
For race detection:
cd src && go test ./... -race
Fix any compilation or test failures before finishing.