Skip to content

Commit f2781b5

Browse files
ostermanclaudeautofix-ci[bot]
authored
refactor: replace t.Skip with t.Skipf throughout codebase (#1449)
* refactor: replace t.Skip with t.Skipf and improve test skipping - Replace all t.Skip() calls with t.Skipf() providing descriptive reasons - Update CLI test infrastructure to use skipReason instead of fatal exits - Add golangci-lint rule to enforce t.Skipf usage - Update CLAUDE.md with test skipping conventions - Ensure TestMain always calls m.Run() for proper test reporting This change improves test debugging by providing clear reasons when tests are skipped, and ensures that missing/stale binaries result in properly reported skipped tests rather than fatal exits. Co-Authored-By: Claude <noreply@anthropic.com> * chore: add tests.test to .gitignore * [autofix.ci] apply automated fixes * fix: re-add forbidigo to test file exclusions The forbidigo linter needs to be excluded from test files because tests legitimately need to use os.Getenv and os.Setenv for setting up test environments. With 223 occurrences across 44 test files, it's not practical to add nolint comments to each one. The t.Skip check will still be enforced through code review and the documented convention in CLAUDE.md. * docs: fix CLAUDE.md to show t.Skipf in all examples Updated the test skipping convention examples to consistently use t.Skipf() instead of t.Skip(), ensuring the documentation matches the actual implementation and reinforces the correct pattern. * docs: clarify TestMain must call os.Exit(m.Run()) for proper exit codes Updated CLAUDE.md to explicitly state that TestMain must call os.Exit(m.Run()) to propagate test exit codes, and clarified that skipReason should be set before calling m.Run(). This ensures proper test process termination and exit code propagation. --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 5d74b41 commit f2781b5

12 files changed

+64
-27
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,4 @@ internal/exec/output.*
5151
# Coverage files
5252
coverage.out
5353
coverage.html
54+
tests.test

.golangci.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ linters:
3737
forbid:
3838
- pattern: os\.Getenv
3939
msg: Use `viper.BindEnv` for new environment variables instead of `os.Getenv`
40+
- pattern: '\.Skip\('
41+
msg: Use `t.Skipf` with a descriptive reason instead of `t.Skip`
4042
funlen:
4143
lines: 60
4244
statements: 40

CLAUDE.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,24 @@ viper.SetEnvPrefix("ATMOS")
154154
- Target >80% coverage, especially for `pkg/` and `internal/exec/`
155155
- **Comments must end with periods**: All comments should be complete sentences ending with a period (enforced by golangci-lint)
156156

157+
### Test Skipping Conventions (MANDATORY)
158+
- **ALWAYS use `t.Skipf()` instead of `t.Skip()`** - Provide clear reasons for skipped tests
159+
- **NEVER use `t.Skipf()` without a reason**
160+
- Examples:
161+
```go
162+
// WRONG: No reason provided
163+
t.Skipf("Skipping test")
164+
165+
// CORRECT: Clear reason with context
166+
t.Skipf("Skipping symlink test on Windows: symlinks require special privileges")
167+
t.Skipf("Skipping test: %s", dynamicReason)
168+
```
169+
- **For CLI tests that depend on rebuilt binaries**:
170+
- Set package-level `skipReason` variable in `TestMain` before calling `m.Run()`
171+
- Individual test functions check and skip with `t.Skipf()` if set
172+
- TestMain MUST call `os.Exit(m.Run())` to propagate the test exit code
173+
- Never use `log.Fatal()` for missing/stale binaries - set `skipReason` instead
174+
157175
### CLI Command Structure & Examples
158176
Atmos uses **embedded markdown files** for maintainable examples:
159177

internal/exec/copy_glob_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func TestShouldExcludePath(t *testing.T) {
107107
// Skipped on Windows.
108108
func TestShouldExcludePath_Directory(t *testing.T) {
109109
if runtime.GOOS == "windows" {
110-
t.Skip("Skipping directory exclusion test on Windows")
110+
t.Skipf("Skipping directory exclusion test on Windows: path handling differs")
111111
}
112112
dir, err := os.MkdirTemp("", "dir-exclude")
113113
if err != nil {
@@ -242,7 +242,7 @@ func TestCopyDirRecursive(t *testing.T) {
242242
// TestProcessDirEntry_Symlink ensures that symlink entries are skipped.
243243
func TestProcessDirEntry_Symlink(t *testing.T) {
244244
if runtime.GOOS == "windows" {
245-
t.Skip("Skipping symlink test on Windows")
245+
t.Skipf("Skipping symlink test on Windows: symlinks require special privileges")
246246
}
247247
srcDir, err := os.MkdirTemp("", "symlink-src")
248248
if err != nil {
@@ -260,7 +260,7 @@ func TestProcessDirEntry_Symlink(t *testing.T) {
260260
}
261261
linkPath := filepath.Join(srcDir, "link.txt")
262262
if err := os.Symlink(targetFile, linkPath); err != nil {
263-
t.Skip("Cannot create symlink on this system, skipping test.")
263+
t.Skipf("Cannot create symlink on this system: insufficient privileges or unsupported filesystem")
264264
}
265265
entries, err := os.ReadDir(srcDir)
266266
if err != nil {
@@ -352,7 +352,7 @@ func TestGetMatchesForPattern_InvalidPattern(t *testing.T) {
352352
// TestGetMatchesForPattern_ShallowNoMatch tests the shallow branch with no matches.
353353
func TestGetMatchesForPattern_ShallowNoMatch(t *testing.T) {
354354
if runtime.GOOS == "windows" {
355-
t.Skip("Skipping shallow no-match test on Windows")
355+
t.Skipf("Skipping shallow no-match test on Windows: glob behavior differs")
356356
}
357357
oldFn := getGlobMatchesForTest
358358
defer func() { getGlobMatchesForTest = oldFn }()
@@ -745,7 +745,7 @@ func TestCopyFile_FailChmod(t *testing.T) {
745745
dstFile := filepath.Join(dstDir, "test.txt")
746746
err = copyFile(srcFile, dstFile)
747747
if err == nil {
748-
t.Skip("os.Chmod patch not effective on this platform")
748+
t.Skipf("Skipping test: os.Chmod not effective on this platform")
749749
}
750750
if !strings.Contains(err.Error(), "setting permissions") {
751751
t.Errorf("Expected chmod error, got %v", err)

internal/exec/template_utils_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
// TestCreateTempDirectory verifies that a temporary directory is created with the expected permissions.
1212
func TestCreateTempDirectory(t *testing.T) {
1313
if runtime.GOOS == "windows" {
14-
t.Skip("Skipping permission check on Windows")
14+
t.Skipf("Skipping permission check on Windows: Unix permissions not applicable")
1515
}
1616

1717
dir, err := createTempDirectory()

pkg/downloader/custom_git_detector_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ func TestDetect_UnsupportedHost(t *testing.T) {
164164

165165
func TestRemoveSymlinks(t *testing.T) {
166166
if runtime.GOOS == "windows" {
167-
t.Skip("Skipping symlink tests on Windows.")
167+
t.Skipf("Skipping symlink tests on Windows: symlinks require special privileges")
168168
}
169169
tempDir, err := os.MkdirTemp("", "symlinktest")
170170
if err != nil {

pkg/downloader/get_git_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ func TestCheckGitVersion_CommandError(t *testing.T) {
520520

521521
func TestCheckGitVersion_WindowsSuffix_Stripped(t *testing.T) {
522522
if runtime.GOOS != "windows" {
523-
t.Skip("windows-specific behavior")
523+
t.Skipf("Skipping test: Windows-specific git behavior differs from Unix systems")
524524
}
525525
// On Windows, version string may contain ".windows." and should be stripped
526526
writeFakeGit(t, "git version 2.20.1.windows.1", 0)

pkg/downloader/git_getter_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func TestRemoveSymlinks_NonexistentRoot_PropagatesError(t *testing.T) {
113113
func TestRemoveSymlinks_WalkError_Propagates(t *testing.T) {
114114
// Permission-denied dir (Unix only; Windows semantics differ)
115115
if runtime.GOOS == "windows" {
116-
t.Skip("permission-based Walk error test skipped on Windows")
116+
t.Skipf("Skipping permission-based Walk error test on Windows: permissions work differently")
117117
}
118118
root := t.TempDir()
119119
denyDir := filepath.Join(root, "deny")
@@ -182,7 +182,7 @@ func TestCustomGitGetter_Get_RemoveSymlinkError(t *testing.T) {
182182
// This test is similar to the success case, but we'll use a read-only directory
183183
// to force a permission error during symlink removal
184184
if runtime.GOOS == "windows" {
185-
t.Skip("Skipping read-only directory test on Windows")
185+
t.Skipf("Skipping read-only directory test on Windows: read-only semantics differ")
186186
}
187187

188188
// Create a read-only directory

pkg/downloader/gogetter_downloader_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ func TestDownloadDetectFormatAndParseFile(t *testing.T) {
147147

148148
func TestGoGetterGet_File(t *testing.T) {
149149
if runtime.GOOS == "windows" {
150-
t.Skip("Skipping file copying test on Windows due to potential file system differences.")
150+
t.Skipf("Skipping file copying test on Windows: file system differences may cause issues")
151151
}
152152
srcDir, err := os.MkdirTemp("", "src")
153153
if err != nil {

pkg/store/google_secret_manager_store_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ func TestNewGSMStore(t *testing.T) {
497497
for _, tt := range tests {
498498
t.Run(tt.name, func(t *testing.T) {
499499
if tt.skipMessage != "" && os.Getenv("GOOGLE_APPLICATION_CREDENTIALS") == "" {
500-
t.Skip(tt.skipMessage)
500+
t.Skipf("%s", tt.skipMessage)
501501
}
502502
store, err := NewGSMStore(tt.options)
503503
if tt.expectError {

0 commit comments

Comments
 (0)