| name | scaffold-integration-test |
| description | Generate HTTP-boundary integration tests for one feature under `internal/integration/`. These are NOT DB/usecase integration tests โ they boot an Echo server via `httptest` and verify only the HTTP path (Router โ Middleware โ Handler โ Presenter) with the usecase MOCKED, per `internal/integration/README.md`'s test strategy. Hardcodes no helper API: reads `internal/integration/README.md` (test strategy + scope) and `internal/integration/helper_test.go` (the package's test helpers โ HTTP server bootstrap, request execution, JSON-response assertion, auth-header injection) at runtime to learn their current names + signatures, plus a sibling `<feature>_test.go` as the structural template, the target handler package's `BindHandler` signature, its generated `gen` request/response types, and the usecase mock package. Derives one subtest per operationId (HTTP method + path from the handler `gen`), each: boot Echo โ mock the mapped usecase method โ bind the handler โ drive the endpoint through whatever request/assert helpers `helper_test.go` exposes โ assert status (+ JSON body on happy path); auth-required operations use the auth-header helper. Writes ONLY `internal/integration/<feature>_test.go`. Verifies with `make fix` + `make test`. Prerequisite: the controller handler for the feature exists and compiles (its `BindHandler` + `gen` are importable) and the usecase mock exists. Standalone-callable; chained from `scaffold-controller` as its final step (so `scaffold-endpoint` gets it transitively). |
Scaffold Integration Test
Generate the HTTP-boundary integration test for a feature under internal/integration/.
This layer is not about DB or usecase internals โ it boots a real Echo server (httptest) and asserts the behavior of the whole HTTP path (Router โ Middleware โ Handler โ Presenter) with the usecase mocked. See internal/integration/README.md for the canonical test strategy and scope.
A Japanese reference translation of this skill is available at SKILL.ja.md in the same directory (not loaded as a skill; for human reference only).
When to Use
- Immediately after a feature's controller handler is implemented and compiles.
- As the final step of
scaffold-controller (auto-chained), so a feature gets its HTTP-boundary test right after the handler exists.
- Standalone when only the integration test for an existing handler needs scaffolding.
Do NOT use for:
- DB / Repository / usecase-logic verification โ those are unit tests (domain/usecase) and the repository's own
make test (real DB). Integration here stops at the HTTP boundary.
- Modifying the handler, usecase, or generated files.
- Adding a single case to an existing
<feature>_test.go โ edit by hand.
What This Skill Reads / Writes
Reads (always, as source of truth):
internal/integration/README.md โ test strategy + scope (what is and is NOT verified here)
internal/integration/helper_test.go โ the package's test helpers, by role: HTTP server bootstrap, request execution, JSON-response assertion, auth-header injection. Read their exact names + signatures from this file at runtime โ the skill hardcodes none of them. Use whatever helpers exist there; do not reinvent HTTP plumbing.
internal/integration/<sibling>_test.go (e.g. v1_users_test.go) โ structural template for the package's idioms
internal/controller/handler/<path>/<feature>_handler.go โ the BindHandler signature + handler package name to import
internal/controller/handler/<path>/gen/server.gen.go โ operationId list + HTTP method/path (from the route comments) + request/response types
- the usecase mock package (e.g.
internal/usecase/<pkg>/mock) โ the mock + EXPECT() method names for the mapped usecase methods
Writes (with confirmation):
internal/integration/<feature>_test.go โ one top-level Test<Feature>_Integration func with one subtest per operationId
Triggers (via make):
make fix + make test โ final verification
Never touches:
- Handler / usecase / domain / infra code
- Generated
*.gen.go
internal/integration/helper_test.go (read-only; if a needed helper is missing, surface it โ do not edit the helper here)
Preconditions
The skill verifies before any write:
internal/integration/ exists with helper_test.go (the helper API is present).
- The target handler package exists and exposes
BindHandler (controller scaffolding done + compiling).
- The usecase mock package for the feature exists (generated).
internal/integration/<feature>_test.go does NOT already exist (abort if it does โ hand back to manual editing).
If any precondition fails, abort with corrective guidance (/scaffold-controller, make gen-api for the mock, manual cleanup).
First Step: Resolve Identity
This skill MUST call AskUserQuestion immediately after invocation (unless invoked from scaffold-controller with feature + handler path + usecase package already in context):
- ่ณชๅ: ใๅฏพ่ฑก feature ๅ (kebab-case) / ๅบๅใใกใคใซๅ (
internal/integration/<feature>_test.go)ใ โ free-text
- ่ณชๅ: ใhandler package ใใน (
internal/controller/handler/ ้
ไธ)ใ โ free-text, validate dir exists
- ่ณชๅ: ใๅฏพๅฟใใ usecase package ๅ (mock ใฎๆๅจ)ใ โ free-text, validate
internal/usecase/<name>/mock exists
Step 1. Read Inputs
- Read
internal/integration/README.md โ re-confirm the scope (HTTP boundary only, usecase mocked, no DB).
- Read
internal/integration/helper_test.go โ enumerate the available helpers and their signatures (do not hardcode; read them this run).
- Read 1 sibling
<sibling>_test.go as the structural template (imports, echo.New(), mock wiring, StartServer, assertions, MakeAvailableUserID for auth).
- Read the handler
gen/server.gen.go โ for each operationId: HTTP method + path (from route comments), request type, response type + the 2xx response constructor.
- Read the handler
<feature>_handler.go โ BindHandler signature + which operations require auth (ctxhelper.GetAuthn usage).
- Read the usecase mock package โ the mock constructor +
EXPECT() method names to stub for each operation.
Step 2. Derive Per-Operation Test Plan
For each operationId in the handler gen:
- HTTP method + path (e.g.
GET /v1/users/{user_id})
- the usecase method the handler calls (read from
<feature>_handler.go) โ the mock EXPECT() to set
- whether the operation requires authentication โ if so, use
MakeAvailableUserID
- happy-path expectation (status + minimal JSON body shape) and, where cheap, one representative error path (e.g. usecase returns
apperror.ErrNotFound โ expect 404) to confirm the errorhandler middleware mapping on the HTTP path
Keep it at the HTTP boundary: assert status codes and response serialization, NOT business outcomes (the usecase is mocked).
Step 3. Test-Perspective Subagent
Invoke the Agent tool (subagent_type: general-purpose) to enumerate HTTP-boundary viewpoints BEFORE writing, passing internal/integration/README.md + the per-operation plan. Expected viewpoints:
- routing reachability (method + path resolves to the handler)
- request deserialization (path param / body) and 2xx response serialization shape
- apperror โ HTTP status mapping along the real middleware stack (e.g. NotFound โ 404, validation โ 422/400)
- auth-required operations: with and (where meaningful) without
MakeAvailableUserID
- middleware effects that only manifest on the full HTTP path (request id, force-json, recovery) when relevant
Output: per-operation subtest list (happy path + the error/auth paths worth asserting at this layer).
Step 4. Plan and Confirm
Display a Japanese summary: output file, per-operation subtests (method + path + mocked usecase method + auth note + expected status), then ask:
- ใไปฅไธใฎๆงๆใง integration ใในใใ็ๆใใพใใ๏ผใ
- Options: ใ็ๆใใใ / ใไฟฎๆญฃใใใ็ฎๆใๆๆใใใ / ใใญใฃใณใปใซใ
Step 5. Write the Test File
Write internal/integration/<feature>_test.go:
package integration
- One
func Test<Feature>_Integration(t *testing.T) with t.Parallel()
- One
t.Run("<ๆฅๆฌ่ชใฎๆฏใ่ใ่ชฌๆ>", ...) per planned subtest. Build each by mirroring the sibling <feature>_test.go and the helpers read in Step 1 โ do not assume helper names; use whatever helper_test.go actually exposes. The shape per subtest:
- boot a fresh Echo instance + a no-op tracer factory + a
gomock controller
- construct the usecase mock and set its
EXPECT() for the mapped method (return canned DTO / error)
- bind the handler via the package's
BindHandler
- for auth-required ops: obtain auth headers via the auth-header helper
- drive the endpoint (method + path + body + headers) through the request helper, capture the response
- assert the status code; on happy path build the expected
gen response struct and compare via the JSON-assert helper
- Japanese subtest names; mirror the sibling file's idioms exactly (the actual helper names, import aliases like
mock_<pkg>, tracer-factory constructor). The sibling test + helper_test.go are the source of truth for every helper call โ the steps above describe roles, not fixed identifiers.
Step 6. Verify
make fix
make test
Environment note: make test requires the dev environment to be running for the DB-backed suites in the same run; bring it up with the dedicated make targets (make serve โ make db-init, which migrates and seeds both local & test DBs โ seed data is assumed by the suite), not raw docker compose and not a bare db-*-migrate-up. If make fix / make test fails on a tool version mismatch (e.g. golangci-lint v1/v2 config error), realign with make install-tools (make sync-tools first if tools.yaml changed) rather than hand-editing PATH.
On failure: surface the failing test output + leave a // TODO: at the problem case + FB summary. No auto-rollback.
Step 7. Closing
<Feature> ใฎ HTTP ๅข็ integration ใในใใ internal/integration/<feature>_test.go ใซ็ๆใใพใใใ
<N> ไปถใฎ subtestใmake test OKใ
Do NOT commit.
AI Modification Scope
Per the "Exception: Skill Execution" clause:
- Write scope:
internal/integration/<feature>_test.go only.
- Aborts if that file already exists.
Remains protected:
internal/integration/helper_test.go (read-only).
- Handler / usecase / domain / infra code and generated files.
Constraints
- โ Verify DB / Repository / usecase business logic here (HTTP boundary only โ usecase is mocked)
- โ Edit
helper_test.go or reinvent HTTP plumbing (use the existing helpers)
- โ Modify handler / usecase / generated files
- โ Overwrite an existing
<feature>_test.go
- โ Skip the test-perspective subagent or the confirmation
AskUserQuestion
- โ Auto-rollback on failure (TODO + FB)
- โ
Japanese user-facing output and Japanese subtest names
- โ
t.Parallel(), generated mocks, existing helpers
- โ
Mirror a sibling
<feature>_test.go as the structural template
- โ
One subtest per operationId; assert status + response serialization
Checklist