🎯 Areas for Improvement
1. Complex Assertions in TestFlattenEvent
Current Issues:
TestFlattenEvent uses assert.True with compound boolean expressions that make failure messages cryptic and hard to debug:
// ❌ CURRENT — hard to diagnose on failure
assert.True(t, len(result) > 0 &&
indexIn(result, "latency_ms=") < indexIn(result, "query=") &&
indexIn(result, "query=") < indexIn(result, "tool="),
"keys should be sorted alphabetically in flattened output: %q", result)
assert.True(t, len(result) >= len("stage=tool_call") &&
result[:len("stage=tool_call")] == "stage=tool_call",
"stage should appear first in flattened output: %q", result)
When this fails you cannot tell which condition violated the assertion. Additionally, the helper indexIn reimplements strings.Index — it should be removed in favour of the standard library.
Recommended Changes:
// ✅ IMPROVED — granular assertions with clear messages
assert.NotEmpty(t, result, "FlattenEvent should return a non-empty string")
assert.True(t, strings.HasPrefix(result, "stage=tool_call"),
"stage should appear first in flattened output: %q", result)
assert.NotContains(t, result, "session_id",
"excluded field should not appear in flattened output")
// Verify alphabetical ordering of remaining keys
assert.Less(t, strings.Index(result, "latency_ms="), strings.Index(result, "query="),
"latency_ms should appear before query in sorted output")
assert.Less(t, strings.Index(result, "query="), strings.Index(result, "tool="),
"query should appear before tool in sorted output")
Why this matters: Each assert.* call produces an independent failure message, making it immediately obvious which property is broken.
2. TestFlattenEvent Should Be Table-Driven
Current Issues:
The test covers only a single input scenario. There are several important edge cases for FlattenEvent that are untested:
- Empty
Stage field
- Empty
Fields map
- All fields excluded (result becomes stage-only or empty)
- No fields excluded
Stage is empty and Fields is empty
Recommended Changes:
func TestFlattenEvent(t *testing.T) {
tests := []struct {
name string
evt AgentEvent
excludeFields []string
wantPrefix string
wantContain []string
wantExclude []string
}{
{
name: "normal event with excluded fields",
evt: AgentEvent{
Stage: "tool_call",
Fields: map[string]string{"tool": "search", "query": "foo", "session_id": "abc"},
},
excludeFields: []string{"session_id"},
wantPrefix: "stage=tool_call",
wantContain: []string{"tool=search", "query=foo"},
wantExclude: []string{"session_id"},
},
{
name: "empty stage",
evt: AgentEvent{Stage: "", Fields: map[string]string{"key": "val"}},
excludeFields: []string{},
wantContain: []string{"key=val"},
},
{
name: "all fields excluded",
evt: AgentEvent{Stage: "plan", Fields: map[string]string{"a": "1"}},
excludeFields: []string{"a"},
wantPrefix: "stage=plan",
},
{
name: "empty event",
evt: AgentEvent{},
excludeFields: []string{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := FlattenEvent(tt.evt, tt.excludeFields)
if tt.wantPrefix != "" {
assert.True(t, strings.HasPrefix(result, tt.wantPrefix),
"result should start with %q, got %q", tt.wantPrefix, result)
}
for _, want := range tt.wantContain {
assert.Contains(t, result, want, "result should contain %q", want)
}
for _, exclude := range tt.wantExclude {
assert.NotContains(t, result, exclude, "result should not contain %q", exclude)
}
})
}
}
3. Missing Test: TestTokenize
Current Issues:
Tokenize is an exported function in mask.go with no dedicated test. It is exercised indirectly via TestTrain, but edge cases are never explicitly validated:
- Empty string → empty slice
- Multiple consecutive spaces
- Leading/trailing whitespace
- Single token
Recommended Test:
func TestTokenize(t *testing.T) {
tests := []struct {
name string
input string
expected []string
}{
{name: "empty string", input: "", expected: []string{}},
{name: "single token", input: "hello", expected: []string{"hello"}},
{name: "multiple tokens", input: "a b c", expected: []string{"a", "b", "c"}},
{name: "extra whitespace", input: " a b ", expected: []string{"a", "b"}},
{name: "key=value tokens", input: "stage=plan action=start", expected: []string{"stage=plan", "action=start"}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := Tokenize(tt.input)
if len(tt.expected) == 0 {
assert.Empty(t, got, "Tokenize(%q) should return empty slice", tt.input)
} else {
assert.Equal(t, tt.expected, got, "Tokenize(%q) mismatch", tt.input)
}
})
}
}
4. Missing Error-Path Test: Train with Empty Line
Current Issues:
Miner.Train returns an error when the input line is empty after masking. This error path is never tested:
// In miner.go:
if len(tokens) == 0 {
return nil, errors.New("agentdrain: Train: empty line after masking")
}
Recommended Addition:
func TestTrainEmptyLine(t *testing.T) {
m, err := NewMiner(DefaultConfig())
require.NoError(t, err, "NewMiner should succeed")
_, err = m.Train("")
assert.Error(t, err, "Train should return an error for an empty line")
assert.Contains(t, err.Error(), "empty line", "error message should mention empty line")
}
5. Missing Error-Path Test: NewMasker with Invalid Regex
Current Issues:
NewMasker returns an error when a mask rule pattern fails to compile, but no test covers this path.
Recommended Addition:
func TestNewMaskerInvalidPattern(t *testing.T) {
rules := []MaskRule{
{Name: "bad-rule", Pattern: "[invalid", Replacement: "<X>"},
}
_, err := NewMasker(rules)
assert.Error(t, err, "NewMasker should return an error for an invalid regex pattern")
assert.Contains(t, err.Error(), "bad-rule", "error should mention the rule name")
}
6. Remove the indexIn Helper
Current Issues:
The custom indexIn helper in the test file reimplements strings.Index without using the standard library. This adds dead code risk (the linter may flag it), and is harder to read than strings.Index.
Recommended Change: Remove indexIn and replace its usages in TestFlattenEvent with strings.Index (see improvement #1 above).
The test file
pkg/agentdrain/miner_test.gohas been selected for quality improvement. This issue provides specific, actionable recommendations to enhance test quality, coverage, and maintainability using testify best practices.Current State
pkg/agentdrain/miner_test.gopkg/agentdrain/miner.go,pkg/agentdrain/mask.go,pkg/agentdrain/coordinator.goStrengths ✅
require.*/assert.*usage — Setup calls userequire.NoError,require.NotNilcorrectly, and validations useassert.*.TestTrain,TestMasking,TestComputeSimilarity,TestMergeTemplate, andTestStageSequenceall uset.Run()with descriptive names.TestConcurrencyexercisesMiner.Trainunder concurrent load, which is essential for a mutex-guarded type.🎯 Areas for Improvement
1. Complex Assertions in
TestFlattenEventCurrent Issues:
TestFlattenEventusesassert.Truewith compound boolean expressions that make failure messages cryptic and hard to debug:When this fails you cannot tell which condition violated the assertion. Additionally, the helper
indexInreimplementsstrings.Index— it should be removed in favour of the standard library.Recommended Changes:
Why this matters: Each
assert.*call produces an independent failure message, making it immediately obvious which property is broken.2.
TestFlattenEventShould Be Table-DrivenCurrent Issues:
The test covers only a single input scenario. There are several important edge cases for
FlattenEventthat are untested:StagefieldFieldsmapStageis empty andFieldsis emptyRecommended Changes:
3. Missing Test:
TestTokenizeCurrent Issues:
Tokenizeis an exported function inmask.gowith no dedicated test. It is exercised indirectly viaTestTrain, but edge cases are never explicitly validated:Recommended Test:
4. Missing Error-Path Test:
Trainwith Empty LineCurrent Issues:
Miner.Trainreturns an error when the input line is empty after masking. This error path is never tested:Recommended Addition:
5. Missing Error-Path Test:
NewMaskerwith Invalid RegexCurrent Issues:
NewMaskerreturns an error when a mask rule pattern fails to compile, but no test covers this path.Recommended Addition:
6. Remove the
indexInHelperCurrent Issues:
The custom
indexInhelper in the test file reimplementsstrings.Indexwithout using the standard library. This adds dead code risk (the linter may flag it), and is harder to read thanstrings.Index.Recommended Change: Remove
indexInand replace its usages inTestFlattenEventwithstrings.Index(see improvement #1 above).📋 Implementation Guidelines
Priority Order
TestTrainEmptyLineandTestNewMaskerInvalidPattern— these are untested error pathsTestTokenize— exported function with no dedicated testTestFlattenEventinto a table-driven test and removeindexInassert.Truecompounds into granular assertionsBest Practices from
scratchpad/testing.mdrequire.*for critical setup (stops test on failure)assert.*for test validations (continues checking)t.Run()and descriptive namesTesting Commands
Acceptance Criteria
TestFlattenEventrefactored to table-driven with at least 4 cases (empty stage, all excluded, normal, empty event)indexInhelper removed;strings.Indexused directlyTestTokenizeadded with edge cases (empty string, extra whitespace, single token, key=value)TestTrainEmptyLineadded to cover theerrors.New("empty line after masking")pathTestNewMaskerInvalidPatternadded to cover invalid regex error pathgo test -v ./pkg/agentdrain/scratchpad/testing.mdAdditional Context
scratchpad/testing.mdfor comprehensive testing patternsPriority: Medium
Effort: Small
Expected Impact: Better error-path coverage, clearer failure messages, easier maintenance
Files Involved:
pkg/agentdrain/miner_test.gopkg/agentdrain/miner.go,pkg/agentdrain/mask.goReferences: