Skip to content

Commit a6010c3

Browse files
authored
test: improve golden file management in integration tests (#9699)
1 parent e0c0416 commit a6010c3

File tree

60 files changed

+5573
-13727
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+5573
-13727
lines changed

integration/README.md

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
# Integration Tests
2+
3+
This directory contains integration tests for Trivy. These tests verify Trivy's behavior by running actual commands and comparing the output against golden files.
4+
5+
## Running Tests
6+
7+
### Run integration tests
8+
```bash
9+
# Run standard integration tests (excludes VM, K8s, and module tests)
10+
mage test:integration
11+
12+
# Run all types of integration tests separately
13+
mage test:integration # Standard integration tests
14+
mage test:module # Wasm module tests
15+
mage test:vm # VM integration tests
16+
mage test:k8s # Kubernetes integration tests
17+
```
18+
19+
### Run specific test
20+
```bash
21+
GOEXPERIMENT=jsonv2 go test -tags=integration -run TestRepository ./integration -v
22+
```
23+
24+
## Golden Files
25+
26+
Golden files store the expected output for integration tests. They are located in `integration/testdata/*.golden`.
27+
28+
### Updating Golden Files
29+
30+
When you make changes that affect test output, you need to update the golden files:
31+
32+
```bash
33+
# Update golden files for standard integration tests
34+
mage test:updateGolden
35+
36+
# Update golden files for Wasm module tests
37+
mage test:updateModuleGolden
38+
39+
# Update golden files for VM integration tests
40+
mage test:updateVMGolden
41+
42+
# Update specific golden files manually
43+
GOEXPERIMENT=jsonv2 go test -tags=integration -run TestRepository ./integration -v -update
44+
```
45+
46+
**Important**:
47+
- Only tests that generate golden files as the canonical source support the `-update` flag
48+
- Tests that reuse golden files from other tests will be **skipped** during updates
49+
- Look for `override: nil` comment in test code to identify canonical source tests
50+
51+
### Golden File Management Strategy
52+
53+
#### 1. Canonical Source Tests (Can Update Golden Files)
54+
55+
These tests generate golden files and should have:
56+
- `override: nil` comment in the code
57+
- No `t.Skipf()` for the `-update` flag
58+
59+
Example:
60+
```go
61+
func TestRepository(t *testing.T) {
62+
// ...
63+
runTest(t, osArgs, tt.golden, format, runOptions{
64+
fakeUUID: "3ff14136-e09f-4df9-80ea-%012d",
65+
override: nil, // Do not use overrides - golden files are generated from this test as the canonical source
66+
})
67+
}
68+
```
69+
70+
#### 2. Consumer Tests (Cannot Update Golden Files)
71+
72+
These tests reuse golden files from canonical source tests and should have:
73+
- `if *update { t.Skipf(...) }` at the beginning of the test function
74+
- `override` functions to adjust for differences (e.g., different artifact names, paths)
75+
- Simplified comment: `Golden files are shared with TestXXX.`
76+
77+
Example:
78+
```go
79+
// TestClientServer tests the client-server mode of Trivy.
80+
//
81+
// Golden files are shared with TestTar or TestRepository.
82+
func TestClientServer(t *testing.T) {
83+
if *update {
84+
t.Skipf("Skipping TestClientServer when -update flag is set. Golden files should be updated via TestTar or TestRepository.")
85+
}
86+
87+
// ...
88+
runTest(t, osArgs, tt.golden, types.FormatJSON, runOptions{
89+
override: overrideFuncs(overrideUID, func(_ *testing.T, want, _ *types.Report) {
90+
want.ArtifactName = "https://github.com/knqyf263/trivy-ci-test"
91+
}),
92+
fakeUUID: "3ff14136-e09f-4df9-80ea-%012d",
93+
})
94+
}
95+
```
96+
97+
### Why Only One Test Updates Each Golden File
98+
99+
**Critical constraint**: Each golden file must be updated by exactly one test function.
100+
101+
If multiple tests update the same golden file, they may introduce subtle differences in the output. This causes the golden file to change every time tests are run, depending on which test executed last. This makes the golden files unstable and defeats their purpose.
102+
103+
**Solution**: Designate one test as the "canonical source" for each golden file. Other tests that want to verify equivalent results share the golden file in read-only mode (with `t.Skipf()` during updates).
104+
105+
### When to Share Golden Files
106+
107+
Share golden files between tests when you want to verify that different commands, flags, or configurations produce equivalent results with the **same output format**:
108+
109+
**Good reasons to share:**
110+
- Testing different input methods that produce the same JSON output (local path vs remote URL vs client-server mode)
111+
- Testing different ways to specify the same configuration (environment variables vs CLI flags vs config files)
112+
- Testing different image sources that produce the same scan results (tar archive vs Docker Engine vs registry)
113+
114+
**Use override functions to handle:**
115+
- Different artifact names or paths
116+
- Different metadata (e.g., image config, repo info)
117+
- Different ReportIDs or UUIDs
118+
- Minor formatting differences in paths (e.g., Windows vs Unix separators)
119+
120+
**Example**: TestTar generates golden files for image scanning, and these are reused by:
121+
- TestDockerEngine (different image source: Docker Engine API)
122+
- TestRegistry (different image source: container registry)
123+
- TestClientServer (different execution mode: client-server)
124+
125+
All of these produce the same JSON format with the same vulnerability data, but with different artifact names and metadata.
126+
127+
### Validation
128+
129+
The test framework automatically validates that:
130+
- Tests updating golden files (`*update == true`) cannot use override functions
131+
- This prevents accidentally updating golden files with modified data
132+
133+
If you try to update a golden file with an override function, the test will fail with:
134+
```
135+
invalid test configuration: cannot use override functions when update=true
136+
```
137+
138+
## Test Organization
139+
140+
### Test Files
141+
142+
Tests are organized by functionality:
143+
144+
- `standalone_tar_test.go` - Container image scanning from tar archives
145+
- `repo_test.go` - Repository and filesystem scanning
146+
- `sbom_test.go` - SBOM scanning and generation
147+
- `client_server_test.go` - Client-server mode
148+
- `docker_engine_test.go` - Docker Engine API integration
149+
- `registry_test.go` - Container registry integration
150+
- `config_test.go` - Configuration handling (CLI flags, env vars, config files)
151+
- `vm_test.go` - Virtual machine image scanning
152+
- `module_test.go` - Wasm module integration
153+
154+
### Test Data Directory Structure
155+
156+
```
157+
integration/testdata/
158+
├── *.golden # Golden files (expected test outputs)
159+
└── fixtures/ # Test input files
160+
├── images/ # Container images (auto-downloaded)
161+
├── vm-images/ # VM images (auto-downloaded)
162+
├── repo/ # Repository and filesystem test data
163+
├── sbom/ # SBOM test files
164+
└── ...
165+
```
166+
167+
**Important**: `testdata/fixtures/images/` and `testdata/fixtures/vm-images/` are automatically downloaded by mage commands:
168+
- `mage test:integration` downloads container images
169+
- `mage test:vm` downloads VM images
170+
171+
If you run tests directly with `go test` without using mage commands, these fixtures will not be present and tests will fail. Use mage commands to ensure fixtures are properly set up.
172+
173+
## Troubleshooting
174+
175+
### Golden file shared between tests shows unexpected differences
176+
177+
1. Identify which test is the canonical source (has `override: nil`)
178+
2. Update golden file from the canonical source test only
179+
3. Adjust override functions in consumer tests to handle differences
180+
181+
### Cannot update golden files for a specific test
182+
183+
1. Check if the test has `if *update { t.Skipf(...) }` - this prevents updates
184+
2. Find the canonical source test mentioned in the skip message
185+
3. Update golden files from the canonical source test instead
186+
187+
## Best Practices
188+
189+
1. **One golden file, one updater**: Each golden file should be updated by exactly one test function
190+
2. **Use `mage test:updateGolden`**: This automatically updates all golden files from canonical source tests
191+
3. **Minimize golden file duplication**: Share golden files when testing equivalent functionality
192+
4. **Keep override functions simple**: Complex overrides may indicate tests shouldn't share golden files
193+
5. **Add `override: nil` comments**: Clearly mark canonical source tests in the code

0 commit comments

Comments
 (0)