|
| 1 | +# Go Test Adapter for OpenShift Tests Extension |
| 2 | + |
| 3 | +This package provides a reusable adapter for running standard Go tests within the OpenShift Tests Extension (OTE) framework. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +The Go test adapter allows you to: |
| 8 | +- Run standard `*_test.go` files as OTE tests |
| 9 | +- Embed compiled test binaries in your test extension |
| 10 | +- Configure test metadata (tags, timeouts, lifecycle) via source code comments |
| 11 | +- Automatically discover tests without manual registration |
| 12 | +- Support both serial and parallel test execution |
| 13 | + |
| 14 | +## Quick Start |
| 15 | + |
| 16 | +### 1. Write Standard Go Tests |
| 17 | + |
| 18 | +Write normal Go tests with metadata in comments: |
| 19 | + |
| 20 | +```go |
| 21 | +package eventttl_test |
| 22 | + |
| 23 | +import "testing" |
| 24 | + |
| 25 | +// Timeout: 60m |
| 26 | +// Tags: Serial |
| 27 | +// Lifecycle: Blocking |
| 28 | +func TestEventTTLController(t *testing.T) { |
| 29 | + // Your test code here |
| 30 | +} |
| 31 | + |
| 32 | +// Tags: Parallel |
| 33 | +// Lifecycle: Informing |
| 34 | +func TestEventTTLValidation(t *testing.T) { |
| 35 | + // This test can run in parallel |
| 36 | +} |
| 37 | +``` |
| 38 | + |
| 39 | +### 2. Configure Your Build |
| 40 | + |
| 41 | +Add to your `Makefile`: |
| 42 | + |
| 43 | +```makefile |
| 44 | +# Directory structure |
| 45 | +TEST_EXTENSION_DIR := cmd/my-operator-tests-ext |
| 46 | +GOTEST_DIR := $(TEST_EXTENSION_DIR)/gotest |
| 47 | +COMPILED_TESTS_DIR := $(GOTEST_DIR)/compiled_tests |
| 48 | + |
| 49 | +# Build individual test binaries |
| 50 | +$(COMPILED_TESTS_DIR)/%.test: test/% |
| 51 | + @mkdir -p $(COMPILED_TESTS_DIR) |
| 52 | + go test -c -o $@ ./$< |
| 53 | + |
| 54 | +# Generate metadata.json from source comments |
| 55 | +$(COMPILED_TESTS_DIR)/metadata.json: test/* |
| 56 | + @mkdir -p $(COMPILED_TESTS_DIR) |
| 57 | + go run github.com/openshift-eng/openshift-tests-extension/pkg/gotest/cmd/generate-metadata \ |
| 58 | + $@ test/eventttl test/encryption |
| 59 | + |
| 60 | +# Build all test binaries |
| 61 | +.PHONY: build-test-binaries |
| 62 | +build-test-binaries: $(COMPILED_TESTS_DIR)/eventttl.test $(COMPILED_TESTS_DIR)/metadata.json |
| 63 | +``` |
| 64 | + |
| 65 | +### 3. Integrate with Your Test Extension |
| 66 | + |
| 67 | +In your test extension's main.go: |
| 68 | + |
| 69 | +```go |
| 70 | +package main |
| 71 | + |
| 72 | +import ( |
| 73 | + "embed" |
| 74 | + "log" |
| 75 | + |
| 76 | + "github.com/openshift-eng/openshift-tests-extension/pkg/extension" |
| 77 | + "github.com/openshift-eng/openshift-tests-extension/pkg/gotest" |
| 78 | +) |
| 79 | + |
| 80 | +//go:embed gotest/compiled_tests/*.test gotest/compiled_tests/metadata.json |
| 81 | +var compiledTests embed.FS |
| 82 | + |
| 83 | +func main() { |
| 84 | + // Configure the gotest adapter |
| 85 | + config := gotest.GoTestAdapterConfig{ |
| 86 | + TestPrefix: "[sig-api-machinery] my-operator", |
| 87 | + CompiledTests: compiledTests, |
| 88 | + CompiledTestsDir: "gotest/compiled_tests", |
| 89 | + MetadataFileName: "metadata.json", |
| 90 | + } |
| 91 | + |
| 92 | + // Build test specs |
| 93 | + specs, err := gotest.BuildExtensionTestSpecs(config) |
| 94 | + if err != nil { |
| 95 | + log.Fatalf("Failed to build test specs: %v", err) |
| 96 | + } |
| 97 | + |
| 98 | + // Register with OTE |
| 99 | + ext := extension.New("my-operator-tests") |
| 100 | + ext.AddTestSpecs(specs) |
| 101 | + ext.Run() |
| 102 | +} |
| 103 | +``` |
| 104 | + |
| 105 | +## Metadata Format |
| 106 | + |
| 107 | +Test metadata is specified in comments above test functions: |
| 108 | + |
| 109 | +### Timeout |
| 110 | + |
| 111 | +Specifies how long the test can run: |
| 112 | + |
| 113 | +```go |
| 114 | +// Timeout: 60m |
| 115 | +func TestLongRunning(t *testing.T) { ... } |
| 116 | +``` |
| 117 | + |
| 118 | +### Tags |
| 119 | + |
| 120 | +Controls test execution mode: |
| 121 | + |
| 122 | +```go |
| 123 | +// Tags: Serial |
| 124 | +func TestSerial(t *testing.T) { ... } // Runs only in serial mode |
| 125 | + |
| 126 | +// Tags: Parallel |
| 127 | +func TestParallel(t *testing.T) { ... } // Can run in parallel |
| 128 | + |
| 129 | +// Tags: Serial, Slow |
| 130 | +func TestSlowSerial(t *testing.T) { ... } // Multiple tags |
| 131 | +``` |
| 132 | + |
| 133 | +**Important**: By default, tests are marked `Serial` for safety. Use `Parallel` tag only if your test is thread-safe. |
| 134 | + |
| 135 | +### Lifecycle |
| 136 | + |
| 137 | +Determines whether test failures block CI: |
| 138 | + |
| 139 | +```go |
| 140 | +// Lifecycle: Blocking |
| 141 | +func TestCritical(t *testing.T) { ... } // Failures block CI |
| 142 | + |
| 143 | +// Lifecycle: Informing |
| 144 | +func TestOptional(t *testing.T) { ... } // Failures don't block CI (default) |
| 145 | +``` |
| 146 | + |
| 147 | +## Architecture |
| 148 | + |
| 149 | +### Build Time |
| 150 | + |
| 151 | +1. **Source Code** → `generate-metadata` tool scans `*_test.go` files |
| 152 | +2. **metadata.json** generated with all test metadata |
| 153 | +3. **Test Binaries** compiled using `go test -c` |
| 154 | +4. Both embedded in test extension binary via `//go:embed` |
| 155 | + |
| 156 | +### Runtime |
| 157 | + |
| 158 | +1. **Extraction**: Embedded binaries extracted to temp directory |
| 159 | +2. **Discovery**: Each binary queried with `-test.list` to find all tests |
| 160 | +3. **Metadata Lookup**: Test metadata loaded from `metadata.json` |
| 161 | +4. **Registration**: ExtensionTestSpecs created for each test |
| 162 | +5. **Execution**: Tests run via `-test.run` with exact test name |
| 163 | + |
| 164 | +## Advanced Usage |
| 165 | + |
| 166 | +### Custom Test Prefix |
| 167 | + |
| 168 | +The `TestPrefix` appears in all test names: |
| 169 | + |
| 170 | +```go |
| 171 | +config := gotest.GoTestAdapterConfig{ |
| 172 | + TestPrefix: "[sig-auth][Late] openshift-apiserver", |
| 173 | + // ... |
| 174 | +} |
| 175 | +``` |
| 176 | + |
| 177 | +Results in test names like: |
| 178 | +``` |
| 179 | +[sig-auth][Late] openshift-apiserver TestAuthentication [Serial] [Timeout:30m] |
| 180 | +``` |
| 181 | + |
| 182 | +### Multiple Test Directories |
| 183 | + |
| 184 | +Generate metadata from multiple directories: |
| 185 | + |
| 186 | +```bash |
| 187 | +go run .../generate-metadata metadata.json \ |
| 188 | + test/eventttl \ |
| 189 | + test/encryption \ |
| 190 | + test/validation |
| 191 | +``` |
| 192 | + |
| 193 | +### Omitting Test Prefix |
| 194 | + |
| 195 | +Set `TestPrefix` to empty string for simple test names: |
| 196 | + |
| 197 | +```go |
| 198 | +config := gotest.GoTestAdapterConfig{ |
| 199 | + TestPrefix: "", // Test names will be just "TestName [Tags]" |
| 200 | + // ... |
| 201 | +} |
| 202 | +``` |
| 203 | + |
| 204 | +## Directory Structure Example |
| 205 | + |
| 206 | +``` |
| 207 | +my-operator/ |
| 208 | +├── test/ |
| 209 | +│ ├── eventttl/ |
| 210 | +│ │ ├── controller_test.go |
| 211 | +│ │ └── validation_test.go |
| 212 | +│ └── encryption/ |
| 213 | +│ └── rotation_test.go |
| 214 | +├── cmd/ |
| 215 | +│ └── my-operator-tests-ext/ |
| 216 | +│ ├── main.go |
| 217 | +│ └── gotest/ |
| 218 | +│ └── compiled_tests/ # Generated at build time |
| 219 | +│ ├── eventttl.test # Embedded binary |
| 220 | +│ ├── encryption.test # Embedded binary |
| 221 | +│ └── metadata.json # Embedded metadata |
| 222 | +└── Makefile |
| 223 | +``` |
| 224 | + |
| 225 | +## Benefits |
| 226 | + |
| 227 | +1. **Reusable**: Same adapter works for all operators |
| 228 | +2. **Type-Safe**: Standard Go testing package |
| 229 | +3. **IDE Support**: Full IDE support for Go tests |
| 230 | +4. **No Manual Registration**: Tests auto-discovered |
| 231 | +5. **Build-Time Metadata**: No runtime parsing needed |
| 232 | +6. **OTE Integration**: Full OTE features (parallel execution, lifecycle, etc.) |
| 233 | + |
| 234 | +## Comparison with Ginkgo Adapter |
| 235 | + |
| 236 | +| Feature | Go Test Adapter | Ginkgo Adapter | |
| 237 | +|---------|----------------|----------------| |
| 238 | +| Test Framework | `testing.T` | Ginkgo/Gomega | |
| 239 | +| Discovery | `-test.list` | Ginkgo outline | |
| 240 | +| Metadata | Comments | Ginkgo labels | |
| 241 | +| Learning Curve | Low (standard Go) | Medium (Ginkgo DSL) | |
| 242 | +| Complexity | Simple | More features | |
| 243 | + |
| 244 | +## Contributing |
| 245 | + |
| 246 | +When contributing to other operators: |
| 247 | +- Use consistent `TestPrefix` format: `[sig-xxx] operator-name` |
| 248 | +- Default to `Serial` and `Informing` for safety |
| 249 | +- Document timeout requirements |
| 250 | +- Use `Blocking` lifecycle only for critical tests |
0 commit comments