The test file pkg/parser/import_cache_test.go has been selected for quality improvement by the Testify Uber Super Expert π§ͺβ¨. This issue provides specific, actionable recommendations to enhance test quality, coverage, and maintainability using testify best practices.
Current State
- Test File:
pkg/parser/import_cache_test.go
- Source File:
pkg/parser/import_cache.go
- Test Functions: 4 test functions (
TestImportCache, TestImportCacheDirectory, TestImportCacheMissingFile, TestImportCacheEmptyCache)
- Lines of Code: 161 lines (test), 175 lines (source)
- Exported Functions Tested:
NewImportCache, Get, Set, GetCacheDir
- Internal Functions NOT Tested:
sanitizePath, validatePathComponents, ensureGitAttributes
Strengths β
- Good structure: Each test function focuses on a distinct scenario (set/get, directory creation, missing file, empty cache).
- Proper cleanup: All tests use
defer os.RemoveAll(tempDir) to clean up temp directories.
- Build tag present: File correctly includes
//go:build !integration at the top.
Areas for Improvement π―
1. Replace Raw Go Testing with Testify Assertions
The entire file uses raw t.Fatalf, t.Errorf, and t.Error instead of the testify library that is standard across this codebase.
Current anti-patterns throughout the file:
// β CURRENT (anti-pattern) - raw error handling
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
if _, err := os.Stat(cachedPath); os.IsNotExist(err) {
t.Errorf("Cache file was not created: %s", cachedPath)
}
if string(content) != string(testContent) {
t.Errorf("Content mismatch. Expected %q, got %q", testContent, content)
}
if !found {
t.Error("Cache entry not found after Set")
}
Recommended replacement:
// β
IMPROVED - testify assertions
require.NoError(t, err, "creating temp dir should succeed")
require.FileExists(t, cachedPath, "cache file should be created at expected path")
assert.Equal(t, string(testContent), string(content), "cached content should match original")
assert.True(t, found, "cache entry should be found after Set")
Why this matters: Testify provides clearer error messages, better test output, and is the standard used throughout this codebase (see scratchpad/testing.md).
Required import:
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
2. Table-Driven Tests for validatePathComponents and sanitizePath
Both sanitizePath and validatePathComponents are internal functions in the same package and are directly testable, yet have zero test coverage. These are security-critical functions (path traversal prevention) that deserve thorough testing.
Recommended: Add table-driven tests for sanitizePath:
func TestSanitizePath(t *testing.T) {
tests := []struct {
name string
input string
expected string
}{
{
name: "simple path",
input: "workflows/test.md",
expected: "workflows_test.md",
},
{
name: "nested path",
input: "a/b/c/file.md",
expected: "a_b_c_file.md",
},
{
name: "already flat",
input: "file.md",
expected: "file.md",
},
{
name: "path with dots cleaned",
input: "a/./b/file.md",
expected: "a_b_file.md",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := sanitizePath(tt.input)
assert.Equal(t, tt.expected, result, "sanitizePath(%q) should return expected value", tt.input)
})
}
}
Recommended: Add table-driven tests for validatePathComponents:
func TestValidatePathComponents(t *testing.T) {
tests := []struct {
name string
owner string
repo string
path string
sha string
shouldErr bool
errMsg string
}{
{
name: "valid components",
owner: "testowner",
repo: "testrepo",
path: "workflows/test.md",
sha: "abc123",
shouldErr: false,
},
{
name: "empty owner",
owner: "",
repo: "testrepo",
path: "test.md",
sha: "abc123",
shouldErr: true,
errMsg: "empty component",
},
{
name: "path traversal in owner",
owner: "../etc",
repo: "testrepo",
path: "test.md",
sha: "abc123",
shouldErr: true,
errMsg: "..",
},
{
name: "absolute path in sha",
owner: "testowner",
repo: "testrepo",
path: "test.md",
sha: "/absolute/path",
shouldErr: true,
errMsg: "absolute path",
},
{
name: "path traversal in path",
owner: "testowner",
repo: "testrepo",
path: "../../etc/passwd",
sha: "abc123",
shouldErr: true,
errMsg: "..",
},
{
name: "empty sha",
owner: "testowner",
repo: "testrepo",
path: "test.md",
sha: "",
shouldErr: true,
errMsg: "empty component",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := validatePathComponents(tt.owner, tt.repo, tt.path, tt.sha)
if tt.shouldErr {
require.Error(t, err, "should return error for: %s", tt.name)
assert.Contains(t, err.Error(), tt.errMsg, "error message should mention: %s", tt.errMsg)
} else {
assert.NoError(t, err, "should not return error for valid components")
}
})
}
}
3. Missing Tests for Security-Critical Set Error Cases
The Set function has validation logic for file size and path traversal that is completely untested. These are critical security controls.
Missing test cases for Set:
func TestImportCacheSet_Validation(t *testing.T) {
tempDir := t.TempDir() // use t.TempDir() instead of manual setup
tests := []struct {
name string
owner string
repo string
path string
sha string
content []byte
shouldErr bool
errMsg string
}{
{
name: "oversized content rejected",
owner: "owner",
repo: "repo",
path: "test.md",
sha: "abc123",
content: make([]byte, 10*1024*1024+1), // 10MB + 1 byte
shouldErr: true,
errMsg: "exceeds maximum",
},
{
name: "path traversal in owner rejected",
owner: "../etc",
repo: "repo",
path: "test.md",
sha: "abc123",
content: []byte("content"),
shouldErr: true,
errMsg: "invalid path components",
},
{
name: "path traversal in path rejected",
owner: "owner",
repo: "repo",
path: "../../etc/passwd",
sha: "abc123",
content: []byte("content"),
shouldErr: true,
errMsg: "invalid path components",
},
{
name: "empty owner rejected",
owner: "",
repo: "repo",
path: "test.md",
sha: "abc123",
content: []byte("content"),
shouldErr: true,
errMsg: "invalid path components",
},
}
cache := NewImportCache(tempDir)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_, err := cache.Set(tt.owner, tt.repo, tt.path, tt.sha, tt.content)
if tt.shouldErr {
require.Error(t, err, "Set should reject: %s", tt.name)
assert.Contains(t, err.Error(), tt.errMsg, "error message should contain %q", tt.errMsg)
} else {
assert.NoError(t, err, "Set should succeed for: %s", tt.name)
}
})
}
}
4. Use t.TempDir() Instead of Manual Temp Directory Management
Go 1.15+ provides t.TempDir() which automatically cleans up after tests and is the modern idiomatic approach.
// β CURRENT - manual temp dir management
tempDir, err := os.MkdirTemp("", "import-cache-test-*")
if err != nil {
t.Fatalf("Failed to create temp dir: %v", err)
}
defer os.RemoveAll(tempDir)
// β
IMPROVED - automatic cleanup with t.TempDir()
tempDir := t.TempDir()
Why this matters: t.TempDir() always cleans up (even on panic), requires no error handling, and is the idiomatic modern Go pattern.
5. Missing Assertion Messages
Many assertions lack context messages that would help diagnose failures.
// β CURRENT - no context
if retrievedPath != cachedPath {
t.Errorf("Path mismatch. Expected %s, got %s", cachedPath, retrievedPath)
}
// β
IMPROVED - testify with descriptive messages
assert.Equal(t, cachedPath, retrievedPath,
"retrieved path from Get should match path returned by Set")
Implementation Guidelines
Priority Order
- High: Add
TestValidatePathComponents and TestSanitizePath β untested security-critical functions
- High: Add
TestImportCacheSet_Validation β untested error paths in Set
- High: Replace all
t.Fatalf/t.Errorf/t.Error with testify assertions
- Medium: Replace
os.MkdirTemp + defer os.RemoveAll with t.TempDir()
- Low: Add descriptive assertion messages throughout
Best Practices from scratchpad/testing.md
- β
Use
require.* for critical setup that should stop the test on failure
- β
Use
assert.* for test validations that can continue on failure
- β
Write table-driven tests with
t.Run() and descriptive names
- β
No mocks or test suites - test real component interactions
- β
Always include helpful assertion messages
Testing Commands
# Run tests for this file
go test -v -run "TestImportCache" ./pkg/parser/
# Run all parser tests
go test -v ./pkg/parser/
# Run full unit tests
make test-unit
Acceptance Criteria
Additional Context
- Repository Testing Guidelines: See
scratchpad/testing.md for comprehensive testing patterns
- Example Tests: Look at
pkg/parser/frontmatter_utils_test.go or pkg/workflow/*_test.go for testify examples
- Security Note:
sanitizePath and validatePathComponents prevent path traversal attacks β thorough testing of these functions is especially important
Priority: Medium
Effort: Small (3-4 hours)
Expected Impact: Better test coverage for security-critical path validation, clearer failure messages, modern Go test patterns
Files Involved:
- Test file:
pkg/parser/import_cache_test.go
- Source file:
pkg/parser/import_cache.go
References:
Generated by Daily Testify Uber Super Expert
The test file
pkg/parser/import_cache_test.gohas been selected for quality improvement by the Testify Uber Super Expert π§ͺβ¨. This issue provides specific, actionable recommendations to enhance test quality, coverage, and maintainability using testify best practices.Current State
pkg/parser/import_cache_test.gopkg/parser/import_cache.goTestImportCache,TestImportCacheDirectory,TestImportCacheMissingFile,TestImportCacheEmptyCache)NewImportCache,Get,Set,GetCacheDirsanitizePath,validatePathComponents,ensureGitAttributesStrengths β
defer os.RemoveAll(tempDir)to clean up temp directories.//go:build !integrationat the top.Areas for Improvement π―
1. Replace Raw Go Testing with Testify Assertions
The entire file uses raw
t.Fatalf,t.Errorf, andt.Errorinstead of the testify library that is standard across this codebase.Current anti-patterns throughout the file:
Recommended replacement:
Why this matters: Testify provides clearer error messages, better test output, and is the standard used throughout this codebase (see
scratchpad/testing.md).Required import:
2. Table-Driven Tests for
validatePathComponentsandsanitizePathBoth
sanitizePathandvalidatePathComponentsare internal functions in the same package and are directly testable, yet have zero test coverage. These are security-critical functions (path traversal prevention) that deserve thorough testing.Recommended: Add table-driven tests for
sanitizePath:Recommended: Add table-driven tests for
validatePathComponents:3. Missing Tests for Security-Critical
SetError CasesThe
Setfunction has validation logic for file size and path traversal that is completely untested. These are critical security controls.Missing test cases for
Set:4. Use
t.TempDir()Instead of Manual Temp Directory ManagementGo 1.15+ provides
t.TempDir()which automatically cleans up after tests and is the modern idiomatic approach.Why this matters:
t.TempDir()always cleans up (even on panic), requires no error handling, and is the idiomatic modern Go pattern.5. Missing Assertion Messages
Many assertions lack context messages that would help diagnose failures.
Implementation Guidelines
Priority Order
TestValidatePathComponentsandTestSanitizePathβ untested security-critical functionsTestImportCacheSet_Validationβ untested error paths inSett.Fatalf/t.Errorf/t.Errorwith testify assertionsos.MkdirTemp+defer os.RemoveAllwitht.TempDir()Best Practices from
scratchpad/testing.mdrequire.*for critical setup that should stop the test on failureassert.*for test validations that can continue on failuret.Run()and descriptive namesTesting Commands
Acceptance Criteria
t.Fatalf/t.Errorf/t.Errorreplaced withrequire.*/assert.*testify assertionsTestSanitizePathadded as table-driven test covering normal and edge casesTestValidatePathComponentsadded as table-driven test covering all validation paths (empty, traversal, absolute)TestImportCacheSet_Validationadded covering oversized content and invalid path componentsos.MkdirTemp+defer os.RemoveAllreplaced witht.TempDir()go test -v -run "TestImportCache|TestSanitizePath|TestValidatePathComponents" ./pkg/parser/scratchpad/testing.md//go:build !integrationremains at top of fileAdditional Context
scratchpad/testing.mdfor comprehensive testing patternspkg/parser/frontmatter_utils_test.goorpkg/workflow/*_test.gofor testify examplessanitizePathandvalidatePathComponentsprevent path traversal attacks β thorough testing of these functions is especially importantPriority: Medium
Effort: Small (3-4 hours)
Expected Impact: Better test coverage for security-critical path validation, clearer failure messages, modern Go test patterns
Files Involved:
pkg/parser/import_cache_test.gopkg/parser/import_cache.goReferences: