-
Notifications
You must be signed in to change notification settings - Fork 73
Description
Context / Problem
The repository layer is split into three parts:
Layer | Purpose |
---|---|
internal/repository |
Declares repository interfaces (ApplicationRepository , EpochRepository , …) and small helpers. |
internal/repository/factory |
Chooses a concrete backend (postgresql , future sqlite , etc.) based on configuration. |
internal/repository/postgresql |
Current production implementation of the interfaces. |
Today we have no dedicated test suite for these layers, so query errors or future back-end additions could break behaviour unnoticed.
Contract-Style Testing
Write one reusable test suite per interface (the contract) that asserts “this is how an ApplicationRepository
must behave.”
Each concrete backend (PostgreSQL now, SQLite later) simply feeds its implementation into that same suite.
Result: you author the behavioural tests once, yet they run against every backend, guaranteeing consistent behaviour and making new back-ends inherit the tests automatically.
Suggested Solution
-
Contract package
internal/repository/contract/
exports functions such as
RunApplicationRepoContract(t *testing.T, repo repository.ApplicationRepository)
.- Each function is a table-driven suite covering happy path, edge cases, and error paths.
-
PostgreSQL implementation
- Test files like
internal/repository/postgresql/app_test.go
call the contract runner with a Postgres-backed repo. - Each test opens a transaction and rolls it back on cleanup to isolate state.
- Test files like
-
Fixture seeding
- Store deterministic seed data in
internal/repository/testdata/*.sql
. - Load these fixtures (via
go:embed
) inside the contract harness immediately after migrations. - Each test still runs in its own SQL transaction; the fixture rows are visible inside the txn and rolled back on cleanup.
-
Helper & factory tests
internal/repository/helpers_test.go
– filter builders, pagination tokens, nil-safety, etc.internal/repository/factory/factory_test.go
– correct backend selection, errors on unknown schemes.
-
Concurrency & race checks
- All tests run under
go test -race
; some uset.Parallel()
to ensure thread safety.
- All tests run under
-
CI integration
- GitHub Actions spins up Postgres, exports
CARTESI_TEST_DATABASE_CONNECTION
, then runsgo test ./internal/repository/... -race
.
- GitHub Actions spins up Postgres, exports
Deliverables & File Layout
Path | Purpose |
---|---|
internal/repository/contract/ |
Contract suites (application.go , epoch.go , …). |
internal/repository/helpers_test.go |
Unit tests for shared helper funcs. |
internal/repository/factory/factory_test.go |
Backend-selection tests. |
internal/repository/postgresql/*_test.go |
Runs contract tests against Postgres impl. |
internal/repository/testdata/*.sql |
Seed fixtures (embedded via go:embed ). |
internal/repository/testutil/db.go |
Connect, migrate, load fixtures, wrap each test in rollback TX. |
Acceptance Criteria
# | Scenario | Expected outcome |
---|---|---|
1 | go test -race ./internal/repository/... |
All tests pass; repository code coverage ≥ 80 % |
2 | Break a JOIN in PostgreSQL repo | Contract test fails with clear assertion |
3 | Pass unknown DSN (foo://… ) to factory |
Factory returns descriptive error |
4 | Parallel run (go test -parallel 8 ) |
No data races; state isolation via per-test TX |
This contract-driven suite will give us a strong regression net for the current PostgreSQL backend and any future database implementations.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status