Skip to content

test(go-modular): tiered coverage gate, CI-safe test tasks, starter test suites - #151

Open
rubiagatra wants to merge 1 commit into
fix/go-modular-signin-headers-datetime-corsfrom
test/go-modular-coverage-gate
Open

test(go-modular): tiered coverage gate, CI-safe test tasks, starter test suites#151
rubiagatra wants to merge 1 commit into
fix/go-modular-signin-headers-datetime-corsfrom
test/go-modular-coverage-gate

Conversation

@rubiagatra

Copy link
Copy Markdown
Contributor

Stacked on #150 (fix/go-modular-signin-headers-datetime-cors) — the new tests assume those fixes. Merge #150 first; this PR's base then retargets to main.

Description 📋

Lifts the template's statement coverage from ~27% to 79.6% overall / 82.1% in modules/, and gives every generated project a coverage gate plus the test infrastructure to keep it there.

moon.yml

  • test, coverage, test-contract now deps: [tidy, generate-swagger]. docs/swagger.json is embedded and gitignored, so on a clean checkout (CI) the tests didn't compile.
  • coverage does mkdir -p build (gitignored, absent on clean checkout; go test won't create it), writes an absolute profile path, renders coverage.html, then runs the gate.
  • New test-contract task for -tags contract tests.

scripts/coverage-gate.sh

Three tiers over one cover profile — overall, <module>/modules/..., and the packages named in COVERAGE_CRITICAL_PACKAGES — checked against COVERAGE_MIN / COVERAGE_MIN_MODULES / COVERAGE_MIN_CRITICAL. All floors ship at 0 (report only): a template can't know a project's baseline, so the ratchet rule (floor = measured − 5, only ever raised) is documented next to the env values instead. Module path is read from go list -m, so nothing is tied to the package name.

coverage gate (build/coverage.out, module go-modular)
  overall     79.6%   (minimum 0%)
  modules     82.1%   (minimum 0%)
  critical        -   (set COVERAGE_CRITICAL_PACKAGES to enable)

pkg/testutils/webhook, pkg/testutils/contract, testdata/*/README.md

Provider-agnostic webhook replay helpers (AssertIdempotent, AssertLateEventIgnored, AssertRejectsBadSignature) and an HTTP record/replay transport behind the contract build tag, each with their own tests. apps/go-modular/.gitignore re-includes testdata/, which the workspace .gitignore drops globally.

Starter suites for the code the template ships

  • modules/user/{services,handler}, modules/auth/services (password, session, verification), internal/middleware, internal/server.
  • modules/auth/fx_test.go, modules/user/fx_test.go — the fx wiring: config validation, route tables, JWT guard, shared JWTAccess.
  • internal/app/app_integration_test.go — the one end-to-end test: real Postgres (testcontainers), migrations + seed, the fx graph exactly as New() builds it minus the listener, seeded admin sign-in, JWT-guarded route. Copy its shape for new modules.

Ported from a downstream project; all addresses are example.com, nothing project-specific. The wiring tests were rewritten for this template's fx composition (downstream still used the Options/NewModule style).

README.md gets a Testing section. templates/go-modular regenerated from apps/go-modular.

Happy to split

If this is too much for one review, natural cut points are: (a) moon.yml + gate script, (b) pkg/testutils/* + testdata/, (c) the test suites. Say the word.

Verified locally: moon run go-modular:coverage green (238 tests, Docker required for the e2e/repository tests); gate exits 1 when a floor is exceeded; critical tier activates with COVERAGE_CRITICAL_PACKAGES=modules/auth.

Type of change 🤔

  • Feature (non breaking change which adds functionality)

Submission checklist ✅

  • I have performed a self review of my changes
  • I have updated the documentation where relevant
  • My changes are well written and all ci is passing

🤖 Generated with Claude Code

…est suites

Lifts the template's statement coverage from ~27% to 79.6% (modules 82.1%) and
gives every generated project a coverage gate and the test infrastructure to
keep it there.

moon.yml
- test / coverage / test-contract now depend on generate-swagger: docs/swagger.json
  is embedded and gitignored, so a clean checkout (CI) failed to compile the tests.
- coverage creates build/ (gitignored, absent on clean checkout), writes an absolute
  profile path, renders coverage.html and runs scripts/coverage-gate.sh.
- New test-contract task runs the `contract`-tagged tests.

scripts/coverage-gate.sh
- Three tiers over one cover profile: overall, <module>/modules/..., and the packages
  listed in COVERAGE_CRITICAL_PACKAGES. Floors come from COVERAGE_MIN,
  COVERAGE_MIN_MODULES, COVERAGE_MIN_CRITICAL and default to 0 (report only): a
  template cannot know a project's baseline, so the ratchet rule (floor = measured - 5,
  only ever raised) is documented next to the env values instead.
- Module path is read from `go list -m`, so the script is not tied to a package name.

pkg/testutils/webhook, pkg/testutils/contract (+ testdata/*/README.md)
- Provider-agnostic webhook replay helpers (idempotency, late-event, bad-signature
  assertions) and an HTTP record/replay transport behind the `contract` build tag,
  with their own tests. apps/go-modular/.gitignore re-includes testdata/, which the
  workspace .gitignore drops globally.

Starter suites for the code the template ships
- modules/user/{services,handler}, modules/auth/services (password, session,
  verification), internal/middleware, internal/server, internal/config.
- modules/auth/fx_test.go and modules/user/fx_test.go cover the fx wiring: config
  validation, route tables, the JWT guard and the shared JWTAccess.
- internal/app/app_integration_test.go is the one end-to-end test: real Postgres via
  testcontainers, migrations + seed, the fx graph as New() builds it (minus the
  listener), seeded admin sign-in and a JWT-guarded route.

README documents the testing workflow; templates/go-modular regenerated from
apps/go-modular.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant