Skip to content

Commit eb48529

Browse files
authored
feat: add ignoreFiles option to suppress file warnings in test directories (#651)
Adds a new TestSuite configuration option `ignoreFiles` that accepts file patterns (e.g., "*.md", "README*") to ignore when collecting test step files. Files matching these patterns are silently skipped without generating warnings, allowing documentation and other non-test files to coexist in test case directories. Defaults to "README*". Signed-off-by: Martin André <[email protected]>
1 parent abf677c commit eb48529

File tree

7 files changed

+117
-3
lines changed

7 files changed

+117
-3
lines changed

docs/testing/reference.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ kindContainers:
1313
testDirs:
1414
- tests/e2e/
1515
timeout: 120
16+
ignoreFiles:
17+
- "*.md"
18+
- "README*"
19+
- ".gitignore"
1620
```
1721
1822
Supported settings:
@@ -39,6 +43,7 @@ reportGranularity | string | What granularity to report failures at. O
3943
reportName | string | The name of report to create. This field is not used unless reportFormat is set. | "kuttl-test"
4044
namespace | string | The namespace to use for tests. This namespace will be created if it does not exist and removed if it was created (unless `skipDelete` is set). If no namespace is set, one will be auto-generated. |
4145
suppress | list of strings | Suppresses log collection of the specified types. Currently only `events` is supported. |
46+
ignoreFiles | list of strings | File patterns (e.g., `*.md`, `README*`) to ignore when collecting test steps. Files matching these patterns will not generate warnings about not matching the expected test file pattern. Setting this field (even to an empty list) overrides the defaults. | `["README*"]`
4247

4348
## TestStep
4449

internal/harness/harness.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ func (h *Harness) LoadTests(dir string) ([]*testcase.Case, error) {
8888
testcase.WithNamespace(h.TestSuite.Namespace),
8989
testcase.WithTimeout(timeout),
9090
testcase.WithLogSuppressions(h.TestSuite.Suppress),
91+
testcase.WithIgnoreFiles(h.TestSuite.IgnoreFiles),
9192
testcase.WithRunLabels(h.RunLabels),
9293
testcase.WithClients(h.Client, h.DiscoveryClient),
9394
testcase.WithTemplateVars(h.TemplateVars)))

internal/testcase/case.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ func WithLogSuppressions(suppressions []string) CaseOption {
7171
}
7272
}
7373

74+
// WithIgnoreFiles sets the list of file patterns to ignore.
75+
func WithIgnoreFiles(patterns []string) CaseOption {
76+
return func(c *Case) {
77+
c.ignoreFiles = patterns
78+
}
79+
}
80+
7481
// WithRunLabels sets the run labels.
7582
func WithRunLabels(runLabels labels.Set) CaseOption {
7683
return func(c *Case) {
@@ -118,6 +125,8 @@ type Case struct {
118125
logger testutils.Logger
119126
// List of log types which should be suppressed.
120127
suppressions []string
128+
// List of file patterns to ignore when collecting test steps.
129+
ignoreFiles []string
121130
// Caution: the Vars element of this struct may be shared with other Case objects.
122131
templateEnv template.Env
123132
}
@@ -378,7 +387,7 @@ func (c *Case) getEagerClients() ([]clientWithKubeConfig, error) {
378387

379388
// LoadTestSteps loads all the test steps for a test case.
380389
func (c *Case) LoadTestSteps() error {
381-
testStepFiles, err := files.CollectTestStepFiles(c.dir, c.logger)
390+
testStepFiles, err := files.CollectTestStepFiles(c.dir, c.logger, c.ignoreFiles)
382391
if err != nil {
383392
return err
384393
}

internal/utils/files/files.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,44 @@ import (
88
testutils "github.com/kudobuilder/kuttl/internal/utils"
99
)
1010

11+
var defaultIgnorePatterns = []string{"README*"}
12+
13+
// matchesAnyPattern checks if a filename matches any of the given patterns.
14+
// Returns true if a match is found, false otherwise.
15+
func matchesAnyPattern(filename string, patterns []string, logger testutils.Logger) bool {
16+
for _, pattern := range patterns {
17+
matched, err := filepath.Match(pattern, filename)
18+
if err != nil {
19+
logger.Logf("Invalid ignore pattern %q: %v", pattern, err)
20+
continue
21+
}
22+
if matched {
23+
return true
24+
}
25+
}
26+
return false
27+
}
28+
1129
// CollectTestStepFiles collects a map of test steps and their associated files
1230
// from a directory.
13-
func CollectTestStepFiles(dir string, logger testutils.Logger) (map[int64][]string, error) {
31+
func CollectTestStepFiles(dir string, logger testutils.Logger, ignorePatterns []string) (map[int64][]string, error) {
1432
testStepFiles := map[int64][]string{}
1533

34+
patterns := ignorePatterns
35+
if patterns == nil {
36+
patterns = defaultIgnorePatterns
37+
}
38+
1639
files, err := os.ReadDir(dir)
1740
if err != nil {
1841
return nil, err
1942
}
2043

2144
for _, file := range files {
45+
if matchesAnyPattern(file.Name(), patterns, logger) {
46+
continue
47+
}
48+
2249
f := kfile.Parse(file.Name())
2350
if f.Type == kfile.TypeUnknown {
2451
logger.Logf("Ignoring %q: %v.", file.Name(), f.Error)

internal/utils/files/files_test.go

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package files
22

33
import (
4+
"fmt"
5+
"strings"
46
"testing"
57

68
"github.com/stretchr/testify/assert"
@@ -9,6 +11,38 @@ import (
911
testutils "github.com/kudobuilder/kuttl/internal/utils"
1012
)
1113

14+
// mockLogger is a simple logger that captures log messages for testing
15+
type mockLogger struct {
16+
messages []string
17+
}
18+
19+
func (m *mockLogger) Log(args ...interface{}) {
20+
m.messages = append(m.messages, fmt.Sprint(args...))
21+
}
22+
23+
func (m *mockLogger) Logf(format string, args ...interface{}) {
24+
m.messages = append(m.messages, fmt.Sprintf(format, args...))
25+
}
26+
27+
func (m *mockLogger) WithPrefix(_ string) testutils.Logger {
28+
return m
29+
}
30+
31+
func (m *mockLogger) Write(p []byte) (n int, err error) {
32+
return len(p), nil
33+
}
34+
35+
func (m *mockLogger) Flush() {}
36+
37+
func (m *mockLogger) hasMessageContaining(substring string) bool {
38+
for _, msg := range m.messages {
39+
if strings.Contains(msg, substring) {
40+
return true
41+
}
42+
}
43+
return false
44+
}
45+
1246
func TestCollectTestStepFiles(t *testing.T) {
1347
for _, tt := range []struct {
1448
path string
@@ -48,9 +82,38 @@ func TestCollectTestStepFiles(t *testing.T) {
4882
},
4983
} {
5084
t.Run(tt.path, func(t *testing.T) {
51-
testStepFiles, err := CollectTestStepFiles(tt.path, testutils.NewTestLogger(t, tt.path))
85+
testStepFiles, err := CollectTestStepFiles(tt.path, testutils.NewTestLogger(t, tt.path), nil)
5286
require.NoError(t, err)
5387
assert.Equal(t, tt.expected, testStepFiles)
5488
})
5589
}
5690
}
91+
92+
func TestCollectTestStepFilesWithIgnorePatterns(t *testing.T) {
93+
t.Run("default patterns ignore README files", func(t *testing.T) {
94+
logger := &mockLogger{}
95+
_, err := CollectTestStepFiles("test_data/with-overrides", logger, nil)
96+
require.NoError(t, err)
97+
98+
assert.False(t, logger.hasMessageContaining("Ignoring \"README.md\""),
99+
"README.md should be silently ignored with default patterns")
100+
})
101+
102+
t.Run("explicit patterns override defaults", func(t *testing.T) {
103+
logger := &mockLogger{}
104+
_, err := CollectTestStepFiles("test_data/with-overrides", logger, []string{})
105+
require.NoError(t, err)
106+
107+
assert.True(t, logger.hasMessageContaining("Ignoring \"README.md\""),
108+
"README.md should generate warning when default patterns are overridden with empty list")
109+
})
110+
111+
t.Run("custom patterns silently ignore matching files", func(t *testing.T) {
112+
logger := &mockLogger{}
113+
_, err := CollectTestStepFiles("test_data/with-overrides", logger, []string{"*.txt", "*.md"})
114+
require.NoError(t, err)
115+
116+
assert.False(t, logger.hasMessageContaining("Ignoring \"README.md\""),
117+
"README.md should be silently ignored with matching custom pattern")
118+
})
119+
}

pkg/apis/testharness/v1beta1/test_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ type TestSuite struct {
9797
// Suppress is used to suppress logs
9898
Suppress []string `json:"suppress"`
9999

100+
// IgnoreFiles is a list of file patterns (e.g., "*.md", "README*") to ignore when collecting test steps.
101+
// Files matching these patterns will not generate warnings about not matching the expected test file pattern.
102+
IgnoreFiles []string `json:"ignoreFiles"`
103+
100104
Config *RestConfig `json:"config,omitempty"`
101105
}
102106

pkg/apis/testharness/v1beta1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)