test(go-modular): tiered coverage gate, CI-safe test tasks, starter test suites - #151
Open
rubiagatra wants to merge 1 commit into
Open
Conversation
…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>
This was referenced Aug 27, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.ymltest,coverage,test-contractnowdeps: [tidy, generate-swagger].docs/swagger.jsonis embedded and gitignored, so on a clean checkout (CI) the tests didn't compile.coveragedoesmkdir -p build(gitignored, absent on clean checkout;go testwon't create it), writes an absolute profile path, renderscoverage.html, then runs the gate.test-contracttask for-tags contracttests.scripts/coverage-gate.shThree tiers over one cover profile — overall,
<module>/modules/..., and the packages named inCOVERAGE_CRITICAL_PACKAGES— checked againstCOVERAGE_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 fromgo list -m, so nothing is tied to the package name.pkg/testutils/webhook,pkg/testutils/contract,testdata/*/README.mdProvider-agnostic webhook replay helpers (
AssertIdempotent,AssertLateEventIgnored,AssertRejectsBadSignature) and an HTTP record/replay transport behind thecontractbuild tag, each with their own tests.apps/go-modular/.gitignorere-includestestdata/, which the workspace.gitignoredrops 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, sharedJWTAccess.internal/app/app_integration_test.go— the one end-to-end test: real Postgres (testcontainers), migrations + seed, the fx graph exactly asNew()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'sfxcomposition (downstream still used theOptions/NewModulestyle).README.mdgets a Testing section.templates/go-modularregenerated fromapps/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:coveragegreen (238 tests, Docker required for the e2e/repository tests); gate exits 1 when a floor is exceeded; critical tier activates withCOVERAGE_CRITICAL_PACKAGES=modules/auth.Type of change 🤔
Submission checklist ✅
🤖 Generated with Claude Code