ga-plugins-cli 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config-patcher.d.ts +20 -50
- package/dist/config-patcher.d.ts.map +1 -1
- package/dist/config-patcher.js +138 -102
- package/dist/config-patcher.js.map +1 -1
- package/dist/index.js +75 -22
- package/dist/index.js.map +1 -1
- package/dist/installer.d.ts +0 -18
- package/dist/installer.d.ts.map +1 -1
- package/dist/installer.js +19 -39
- package/dist/installer.js.map +1 -1
- package/dist/types.d.ts +10 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/uninstaller.d.ts +0 -23
- package/dist/uninstaller.d.ts.map +1 -1
- package/dist/uninstaller.js +22 -68
- package/dist/uninstaller.js.map +1 -1
- package/package.json +3 -2
- package/plugins/go-reviewer/.claude-plugin/plugin.json +12 -0
- package/plugins/go-reviewer/commands/go-review.md +424 -0
- package/plugins/go-reviewer/mcp-servers/go-reviewer-mcp/README.md +236 -0
- package/plugins/go-reviewer/mcp-servers/go-reviewer-mcp/main.go +678 -0
- package/plugins/go-scaffolder/.claude-plugin/plugin.json +12 -0
- package/plugins/go-scaffolder/commands/scaffold-service.md +802 -0
- package/plugins/go-scaffolder/reference-service/.env.example +27 -0
- package/plugins/go-scaffolder/reference-service/Dockerfile +55 -0
- package/plugins/go-scaffolder/reference-service/REFERENCE-SERVICE-NOTICE.md +104 -0
- package/plugins/go-scaffolder/reference-service/cmd/server/main.go +266 -0
- package/plugins/go-scaffolder/reference-service/config/config.go +67 -0
- package/plugins/go-scaffolder/reference-service/go.mod +17 -0
- package/plugins/go-scaffolder/reference-service/internal/domain/booking.go +118 -0
- package/plugins/go-scaffolder/reference-service/internal/handler/booking.go +242 -0
- package/plugins/go-scaffolder/reference-service/internal/handler/booking_test.go +451 -0
- package/plugins/go-scaffolder/reference-service/internal/repository/booking_postgres.go +124 -0
- package/plugins/go-scaffolder/reference-service/internal/usecase/booking.go +181 -0
- package/plugins/go-standards/.claude-plugin/plugin.json +22 -0
- package/plugins/go-standards/commands/go-standards-check.md +232 -0
- package/plugins/go-standards/skills/concurrency.md +336 -0
- package/plugins/go-standards/skills/config.md +267 -0
- package/plugins/go-standards/skills/error-handling.md +286 -0
- package/plugins/go-standards/skills/http-chi.md +390 -0
- package/plugins/go-standards/skills/logging-observability.md +340 -0
- package/plugins/go-standards/skills/naming-and-style.md +315 -0
- package/plugins/go-standards/skills/project-layout.md +313 -0
- package/plugins/go-standards/skills/testing.md +366 -0
- package/plugins/java2go-porter/.claude-plugin/plugin.json +21 -0
- package/plugins/java2go-porter/agents/analyzer.md +232 -0
- package/plugins/java2go-porter/agents/reviewer.md +241 -0
- package/plugins/java2go-porter/agents/test-pairer.md +365 -0
- package/plugins/java2go-porter/agents/translator.md +419 -0
- package/plugins/java2go-porter/commands/port-java-service.md +149 -0
- package/plugins/java2go-porter/skills/idiom-mapping.md +75 -0
- package/plugins/migration-safety/.claude-plugin/plugin.json +20 -0
- package/plugins/migration-safety/commands/gen-characterization-test.md +452 -0
- package/plugins/migration-safety/commands/strangler-plan.md +356 -0
- package/plugins/migration-safety/skills/strangler-fig.md +382 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
# Command: gen-characterization-test
|
|
2
|
+
|
|
3
|
+
Generate characterization test scaffolding that captures the behavioral contract of the OLD Java service, so that the new Go service can be validated against it. This command produces test scaffolding — a human must run the Java service to capture actual golden data.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Step 1: Identify the Service
|
|
8
|
+
|
|
9
|
+
Ask the user:
|
|
10
|
+
|
|
11
|
+
> "What is the name or path of the Java service you want to characterize?
|
|
12
|
+
> (e.g., `services/booking-java-svc` or just `booking-svc`)"
|
|
13
|
+
|
|
14
|
+
Record as `<service-name>` and `<service-path>`.
|
|
15
|
+
|
|
16
|
+
If a path was given, check that the directory exists and contains Java source files. If not, inform the user and ask to clarify.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Step 2: Choose the Test Format
|
|
21
|
+
|
|
22
|
+
Present the following options to the user:
|
|
23
|
+
|
|
24
|
+
> "Choose a characterization test format:
|
|
25
|
+
>
|
|
26
|
+
> **Option A — Golden JSON files** (recommended default)
|
|
27
|
+
> Simple. No extra tooling. Capture request/response pairs as JSON fixtures.
|
|
28
|
+
> Good for: small teams, early migration phase, services with stable contracts.
|
|
29
|
+
> Requires: manually running the Java service and saving HTTP responses as `.json` files.
|
|
30
|
+
>
|
|
31
|
+
> **Option B — Pact consumer-driven contracts**
|
|
32
|
+
> Stronger cross-team contracts. Versioned. Detectable breaking changes.
|
|
33
|
+
> Requires: a running Pact broker (e.g., PactFlow), Pact Go library.
|
|
34
|
+
> Good for: services consumed by multiple teams, long migration timelines.
|
|
35
|
+
>
|
|
36
|
+
> **Option C — HTTP recording (VCR-style)**
|
|
37
|
+
> Record real traffic against the Java service, replay against the Go service.
|
|
38
|
+
> Requires: HTTP recording library (e.g., `dnaeon/go-vcr`), Java service running during recording.
|
|
39
|
+
> Good for: services with complex request/response sequences.
|
|
40
|
+
>
|
|
41
|
+
> **NEEDS DECISION** — choose A, B, or C. If you proceed without choosing, Option A (golden JSON) will be used as the default."
|
|
42
|
+
|
|
43
|
+
If the user does not choose, default to Option A and note this in the generated output.
|
|
44
|
+
|
|
45
|
+
Record the choice as `<test-format>`.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Step 3: Identify Endpoints to Cover
|
|
50
|
+
|
|
51
|
+
Ask the user:
|
|
52
|
+
|
|
53
|
+
> "Which endpoints should be covered by characterization tests?
|
|
54
|
+
> You can say 'all' to cover every endpoint, or list specific ones (e.g., `POST /api/v1/bookings`, `GET /api/v1/bookings/{id}`)."
|
|
55
|
+
|
|
56
|
+
If the user says "all" and a path was provided, scan the Java source for `@GetMapping`, `@PostMapping`, `@PutMapping`, `@DeleteMapping`, `@PatchMapping`, `@RequestMapping` annotations and list all found endpoints. Show the list to the user and confirm.
|
|
57
|
+
|
|
58
|
+
Record as `<endpoint-list>`.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Step 4: Identify the Corresponding Go Service
|
|
63
|
+
|
|
64
|
+
Ask the user:
|
|
65
|
+
|
|
66
|
+
> "What is the path to the new Go service draft that these tests will validate against?
|
|
67
|
+
> (e.g., `flight-ops-svc/draft-booking-java-svc/` or the final merged service path)"
|
|
68
|
+
|
|
69
|
+
Record as `<go-service-path>`.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Step 5: Generate Scaffolding Based on Format
|
|
74
|
+
|
|
75
|
+
### Format A: Golden JSON Files
|
|
76
|
+
|
|
77
|
+
Create the following structure:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
<go-service-path>/
|
|
81
|
+
testdata/
|
|
82
|
+
golden/
|
|
83
|
+
README.md # instructions for capturing golden data
|
|
84
|
+
<endpoint-slug>/
|
|
85
|
+
<scenario-name>_request.json # HTTP request body fixture
|
|
86
|
+
<scenario-name>_response.json # PLACEHOLDER — must be filled by human
|
|
87
|
+
characterization_test.go # Go test loading fixtures and comparing responses
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
#### testdata/golden/README.md
|
|
91
|
+
|
|
92
|
+
Write:
|
|
93
|
+
|
|
94
|
+
```markdown
|
|
95
|
+
# Golden Data Capture Instructions
|
|
96
|
+
|
|
97
|
+
These JSON files capture the known-good behavior of the Java service: `<service-name>`.
|
|
98
|
+
They are used by `characterization_test.go` to verify the Go service produces equivalent responses.
|
|
99
|
+
|
|
100
|
+
## How to Capture Golden Data
|
|
101
|
+
|
|
102
|
+
1. Start the Java service locally or in a test environment:
|
|
103
|
+
```
|
|
104
|
+
cd <service-path>
|
|
105
|
+
mvn spring-boot:run
|
|
106
|
+
# or: java -jar target/<service-name>.jar
|
|
107
|
+
```
|
|
108
|
+
The service should be running on its default port (check application.properties).
|
|
109
|
+
|
|
110
|
+
2. For each `*_request.json` file in this directory, send the request to the Java service:
|
|
111
|
+
```
|
|
112
|
+
curl -s -X <METHOD> http://localhost:<PORT><PATH> \
|
|
113
|
+
-H "Content-Type: application/json" \
|
|
114
|
+
-d @<endpoint-slug>/<scenario>_request.json \
|
|
115
|
+
> <endpoint-slug>/<scenario>_response.json
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
3. Capture the HTTP status code separately:
|
|
119
|
+
```
|
|
120
|
+
curl -s -o /dev/null -w "%{http_code}" -X <METHOD> http://localhost:<PORT><PATH> \
|
|
121
|
+
-H "Content-Type: application/json" \
|
|
122
|
+
-d @<endpoint-slug>/<scenario>_request.json
|
|
123
|
+
```
|
|
124
|
+
Update the `expectedStatus` field in `characterization_test.go` for each scenario.
|
|
125
|
+
|
|
126
|
+
4. Repeat for error scenarios (invalid input, not-found IDs, unauthorized requests).
|
|
127
|
+
|
|
128
|
+
5. Once all `*_response.json` files are populated, remove the `t.Skip()` calls from `characterization_test.go`.
|
|
129
|
+
|
|
130
|
+
## Important Notes
|
|
131
|
+
|
|
132
|
+
- Capture responses from the Java service BEFORE switching any traffic to Go.
|
|
133
|
+
- If the Java service uses a database, seed the same test data before each capture run.
|
|
134
|
+
- Store the DB seed script in `testdata/sql/seed.sql`.
|
|
135
|
+
- Do NOT commit real customer data as golden fixtures — use synthetic test data only.
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### characterization_test.go
|
|
139
|
+
|
|
140
|
+
Write:
|
|
141
|
+
|
|
142
|
+
```go
|
|
143
|
+
// AUTO-GENERATED CHARACTERIZATION TEST SCAFFOLDING
|
|
144
|
+
// Purpose: verify Go service <go-service-path> produces equivalent responses to Java <service-name>
|
|
145
|
+
// Format: Golden JSON (Option A)
|
|
146
|
+
//
|
|
147
|
+
// BEFORE RUNNING:
|
|
148
|
+
// 1. Read testdata/golden/README.md
|
|
149
|
+
// 2. Capture golden data from the running Java service
|
|
150
|
+
// 3. Remove t.Skip() calls for populated fixtures
|
|
151
|
+
//
|
|
152
|
+
// Run: go test -v ./... -run Characterization
|
|
153
|
+
|
|
154
|
+
package characterization_test
|
|
155
|
+
|
|
156
|
+
import (
|
|
157
|
+
"encoding/json"
|
|
158
|
+
"net/http"
|
|
159
|
+
"net/http/httptest"
|
|
160
|
+
"os"
|
|
161
|
+
"path/filepath"
|
|
162
|
+
"testing"
|
|
163
|
+
|
|
164
|
+
"github.com/go-chi/chi/v5"
|
|
165
|
+
"github.com/stretchr/testify/assert"
|
|
166
|
+
"github.com/stretchr/testify/require"
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
// goldenDir is the root of the golden fixture directory.
|
|
170
|
+
const goldenDir = "testdata/golden"
|
|
171
|
+
|
|
172
|
+
// CharacterizationScenario describes one request/response fixture pair.
|
|
173
|
+
type CharacterizationScenario struct {
|
|
174
|
+
Name string
|
|
175
|
+
Method string
|
|
176
|
+
Path string
|
|
177
|
+
RequestFile string // relative to goldenDir
|
|
178
|
+
ResponseFile string // relative to goldenDir — PLACEHOLDER until captured from Java
|
|
179
|
+
ExpectedStatus int // update after capturing from Java service
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// scenarios lists every endpoint and scenario to characterize.
|
|
183
|
+
// TODO(human): populate ExpectedStatus for each scenario after running Java service.
|
|
184
|
+
// TODO(human): add additional scenarios (error cases, edge cases) as you discover them.
|
|
185
|
+
var scenarios = []CharacterizationScenario{
|
|
186
|
+
// Generated from endpoint list: <endpoint-list>
|
|
187
|
+
{
|
|
188
|
+
Name: "create booking - valid request",
|
|
189
|
+
Method: http.MethodPost,
|
|
190
|
+
Path: "/api/v1/bookings",
|
|
191
|
+
RequestFile: "create_booking/valid_request.json",
|
|
192
|
+
ResponseFile: "create_booking/valid_response.json",
|
|
193
|
+
ExpectedStatus: 201, // TODO(human): verify against actual Java response
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
Name: "create booking - invalid body",
|
|
197
|
+
Method: http.MethodPost,
|
|
198
|
+
Path: "/api/v1/bookings",
|
|
199
|
+
RequestFile: "create_booking/invalid_body_request.json",
|
|
200
|
+
ResponseFile: "create_booking/invalid_body_response.json",
|
|
201
|
+
ExpectedStatus: 400, // TODO(human): verify against actual Java response
|
|
202
|
+
},
|
|
203
|
+
// TODO(human): add one scenario per endpoint in <endpoint-list>
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
func TestCharacterization_GoldenJSON(t *testing.T) {
|
|
207
|
+
t.Skip("NEEDS GOLDEN DATA: read testdata/golden/README.md, run Java service, capture responses. Remove this Skip when all *_response.json files are populated.")
|
|
208
|
+
|
|
209
|
+
// TODO(human): initialize Go service router here
|
|
210
|
+
// Example:
|
|
211
|
+
// cfg, _ := config.Load()
|
|
212
|
+
// db, _ := database.New(cfg.DatabaseURL)
|
|
213
|
+
// ... wire dependencies ...
|
|
214
|
+
// r := chi.NewRouter()
|
|
215
|
+
// handler.NewBookingHandler(bookingUC).RegisterRoutes(r)
|
|
216
|
+
var r chi.Router // replace with your real router initialization
|
|
217
|
+
_ = r
|
|
218
|
+
|
|
219
|
+
server := httptest.NewServer(r)
|
|
220
|
+
defer server.Close()
|
|
221
|
+
|
|
222
|
+
for _, sc := range scenarios {
|
|
223
|
+
t.Run(sc.Name, func(t *testing.T) {
|
|
224
|
+
// Load request fixture
|
|
225
|
+
reqPath := filepath.Join(goldenDir, sc.RequestFile)
|
|
226
|
+
reqBody, err := os.ReadFile(reqPath)
|
|
227
|
+
require.NoError(t, err, "request fixture must exist: %s — create it if missing", reqPath)
|
|
228
|
+
|
|
229
|
+
// Send request to Go service
|
|
230
|
+
req, err := http.NewRequest(sc.Method, server.URL+sc.Path, bytesReader(reqBody))
|
|
231
|
+
require.NoError(t, err)
|
|
232
|
+
req.Header.Set("Content-Type", "application/json")
|
|
233
|
+
|
|
234
|
+
resp, err := http.DefaultClient.Do(req)
|
|
235
|
+
require.NoError(t, err)
|
|
236
|
+
defer resp.Body.Close()
|
|
237
|
+
|
|
238
|
+
// Check status code
|
|
239
|
+
assert.Equal(t, sc.ExpectedStatus, resp.StatusCode,
|
|
240
|
+
"HTTP status mismatch for %s %s", sc.Method, sc.Path)
|
|
241
|
+
|
|
242
|
+
// Load response fixture
|
|
243
|
+
respPath := filepath.Join(goldenDir, sc.ResponseFile)
|
|
244
|
+
goldenBody, err := os.ReadFile(respPath)
|
|
245
|
+
require.NoError(t, err,
|
|
246
|
+
"response fixture must exist: %s — capture from Java service first", respPath)
|
|
247
|
+
|
|
248
|
+
// Compare response bodies (JSON-normalized)
|
|
249
|
+
var golden, actual interface{}
|
|
250
|
+
require.NoError(t, json.Unmarshal(goldenBody, &golden))
|
|
251
|
+
require.NoError(t, json.NewDecoder(resp.Body).Decode(&actual))
|
|
252
|
+
assert.Equal(t, golden, actual,
|
|
253
|
+
"response body mismatch for %s %s — Go response differs from Java golden", sc.Method, sc.Path)
|
|
254
|
+
})
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
func bytesReader(b []byte) *bytes.Reader {
|
|
259
|
+
return bytes.NewReader(b)
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Also create placeholder request fixture files. For each endpoint, write a minimal `*_request.json` placeholder:
|
|
264
|
+
|
|
265
|
+
```json
|
|
266
|
+
{
|
|
267
|
+
"_PLACEHOLDER": true,
|
|
268
|
+
"_instructions": "Replace this file with a real request body for the Java service endpoint.",
|
|
269
|
+
"_endpoint": "<METHOD> <PATH>"
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
And a minimal `*_response.json` placeholder:
|
|
274
|
+
|
|
275
|
+
```json
|
|
276
|
+
{
|
|
277
|
+
"_PLACEHOLDER": true,
|
|
278
|
+
"_instructions": "Run the Java service and capture the real response here. See testdata/golden/README.md.",
|
|
279
|
+
"_endpoint": "<METHOD> <PATH>"
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
### Format B: Pact Consumer-Driven Contracts
|
|
286
|
+
|
|
287
|
+
Create:
|
|
288
|
+
|
|
289
|
+
```
|
|
290
|
+
<go-service-path>/
|
|
291
|
+
contract/
|
|
292
|
+
pact/
|
|
293
|
+
<service-name>_pact_test.go # Pact consumer test skeleton
|
|
294
|
+
README.md # Pact setup instructions
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Write `<service-name>_pact_test.go`:
|
|
298
|
+
|
|
299
|
+
```go
|
|
300
|
+
// AUTO-GENERATED PACT CONTRACT TEST SCAFFOLDING
|
|
301
|
+
// Format: Pact consumer-driven contracts (Option B)
|
|
302
|
+
//
|
|
303
|
+
// BEFORE RUNNING:
|
|
304
|
+
// 1. Install Pact Go: go get github.com/pact-foundation/pact-go/v2
|
|
305
|
+
// 2. Set up a Pact broker (PactFlow or self-hosted)
|
|
306
|
+
// 3. Set PACT_BROKER_URL, PACT_BROKER_TOKEN environment variables
|
|
307
|
+
// 4. Fill in interaction expectations below based on actual Java service behavior
|
|
308
|
+
//
|
|
309
|
+
// Run: go test -v ./contract/pact/...
|
|
310
|
+
|
|
311
|
+
package pact_test
|
|
312
|
+
|
|
313
|
+
import (
|
|
314
|
+
"fmt"
|
|
315
|
+
"testing"
|
|
316
|
+
|
|
317
|
+
"github.com/pact-foundation/pact-go/v2/consumer"
|
|
318
|
+
"github.com/pact-foundation/pact-go/v2/matchers"
|
|
319
|
+
"github.com/stretchr/testify/require"
|
|
320
|
+
)
|
|
321
|
+
|
|
322
|
+
func TestPact_<ServiceName>_CreateBooking(t *testing.T) {
|
|
323
|
+
t.Skip("NEEDS SETUP: configure Pact broker and fill in interaction expectations from Java service behavior")
|
|
324
|
+
|
|
325
|
+
mockProvider, err := consumer.NewV2Pact(consumer.MockHTTPProviderConfig{
|
|
326
|
+
Consumer: "go-<go-service-name>",
|
|
327
|
+
Provider: "java-<service-name>",
|
|
328
|
+
})
|
|
329
|
+
require.NoError(t, err)
|
|
330
|
+
|
|
331
|
+
// TODO(human): define interactions based on observed Java service behavior
|
|
332
|
+
err = mockProvider.
|
|
333
|
+
AddInteraction().
|
|
334
|
+
Given("a valid booking request").
|
|
335
|
+
UponReceiving("a POST /api/v1/bookings request").
|
|
336
|
+
WithRequest("POST", "/api/v1/bookings").
|
|
337
|
+
WithHeader("Content-Type", matchers.S("application/json")).
|
|
338
|
+
WithBody(matchers.MapMatcher{
|
|
339
|
+
"flightId": matchers.S("FL-001"),
|
|
340
|
+
"seatCount": matchers.Integer(2),
|
|
341
|
+
"passengerId": matchers.S("P-001"),
|
|
342
|
+
}).
|
|
343
|
+
WillRespondWith(201).
|
|
344
|
+
WithHeader("Content-Type", matchers.S("application/json")).
|
|
345
|
+
WithBody(matchers.MapMatcher{
|
|
346
|
+
"id": matchers.Regex("BK-[0-9]+", "BK-001"),
|
|
347
|
+
"status": matchers.S("PENDING"),
|
|
348
|
+
}).
|
|
349
|
+
ExecuteTest(t, func(config consumer.MockServerConfig) error {
|
|
350
|
+
// TODO(human): call your Go service client against config.Host:config.Port
|
|
351
|
+
return fmt.Errorf("implement me: call Go client against mock provider")
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
require.NoError(t, err)
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
---
|
|
359
|
+
|
|
360
|
+
### Format C: HTTP Recording (VCR-Style)
|
|
361
|
+
|
|
362
|
+
Create:
|
|
363
|
+
|
|
364
|
+
```
|
|
365
|
+
<go-service-path>/
|
|
366
|
+
testdata/
|
|
367
|
+
cassettes/ # VCR cassette files (recorded HTTP interactions)
|
|
368
|
+
<endpoint-slug>_<scenario>.yaml # PLACEHOLDER — recorded by running cassette capture
|
|
369
|
+
vcr_characterization_test.go # Test using go-vcr to replay cassettes
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
Write `vcr_characterization_test.go`:
|
|
373
|
+
|
|
374
|
+
```go
|
|
375
|
+
// AUTO-GENERATED VCR CHARACTERIZATION TEST SCAFFOLDING
|
|
376
|
+
// Format: HTTP recording / VCR-style (Option C)
|
|
377
|
+
//
|
|
378
|
+
// BEFORE RUNNING:
|
|
379
|
+
// 1. Install go-vcr: go get github.com/dnaeon/go-vcr/v3
|
|
380
|
+
// 2. Run the Java service locally
|
|
381
|
+
// 3. Set RECORD_MODE=true and run tests once to record cassettes
|
|
382
|
+
// 4. Commit the cassette YAML files
|
|
383
|
+
// 5. Run tests normally to replay cassettes against the Go service
|
|
384
|
+
//
|
|
385
|
+
// Run: go test -v ./... -run VCR
|
|
386
|
+
|
|
387
|
+
package characterization_test
|
|
388
|
+
|
|
389
|
+
import (
|
|
390
|
+
"net/http"
|
|
391
|
+
"testing"
|
|
392
|
+
|
|
393
|
+
"github.com/dnaeon/go-vcr/v3/cassette"
|
|
394
|
+
"github.com/dnaeon/go-vcr/v3/recorder"
|
|
395
|
+
"github.com/stretchr/testify/assert"
|
|
396
|
+
"github.com/stretchr/testify/require"
|
|
397
|
+
)
|
|
398
|
+
|
|
399
|
+
func TestVCR_<ServiceName>_Characterization(t *testing.T) {
|
|
400
|
+
t.Skip("NEEDS GOLDEN DATA: set JAVA_SERVICE_URL, run with RECORD_MODE=true against Java service first. See testdata/cassettes/ README.")
|
|
401
|
+
|
|
402
|
+
cassetteFile := "testdata/cassettes/create_booking_valid"
|
|
403
|
+
|
|
404
|
+
r, err := recorder.New(cassetteFile)
|
|
405
|
+
require.NoError(t, err)
|
|
406
|
+
defer r.Stop()
|
|
407
|
+
|
|
408
|
+
// TODO(human): point this at your Go service URL, not the Java service
|
|
409
|
+
// In record mode (cassette missing), it records against Java service
|
|
410
|
+
// In replay mode (cassette exists), it replays against Go service
|
|
411
|
+
client := &http.Client{Transport: r}
|
|
412
|
+
_ = client
|
|
413
|
+
|
|
414
|
+
// TODO(human): make HTTP requests using `client` and assert responses
|
|
415
|
+
assert.Fail(t, "implement VCR test body")
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
---
|
|
420
|
+
|
|
421
|
+
## Step 6: Output Checklist
|
|
422
|
+
|
|
423
|
+
After generating scaffolding, print:
|
|
424
|
+
|
|
425
|
+
```
|
|
426
|
+
==========================================================================
|
|
427
|
+
CHARACTERIZATION TEST SCAFFOLDING GENERATED
|
|
428
|
+
Format: <test-format> (<A/B/C>)
|
|
429
|
+
Output: <go-service-path>/
|
|
430
|
+
|
|
431
|
+
WHAT YOU MUST DO NEXT TO CAPTURE GOLDEN DATA:
|
|
432
|
+
|
|
433
|
+
[ ] 1. Start the Java service: <service-name>
|
|
434
|
+
(see service README or run: mvn spring-boot:run in <service-path>)
|
|
435
|
+
|
|
436
|
+
[ ] 2. Set up test data in the database (if needed):
|
|
437
|
+
Run: psql -f testdata/sql/seed.sql <database-name>
|
|
438
|
+
(seed.sql must be written by the team — use synthetic data only, no real PII)
|
|
439
|
+
|
|
440
|
+
[ ] 3. For each endpoint in <endpoint-list>:
|
|
441
|
+
Send the requests and capture responses:
|
|
442
|
+
See testdata/golden/README.md for exact curl commands (Format A)
|
|
443
|
+
OR follow Pact setup in contract/pact/README.md (Format B)
|
|
444
|
+
OR run with RECORD_MODE=true (Format C)
|
|
445
|
+
|
|
446
|
+
[ ] 4. Remove t.Skip() calls as you populate each fixture
|
|
447
|
+
|
|
448
|
+
[ ] 5. Run the tests against the Go service: go test -v ./...
|
|
449
|
+
|
|
450
|
+
[ ] 6. All tests must pass before declaring the Go service ready for traffic
|
|
451
|
+
==========================================================================
|
|
452
|
+
```
|