Re-enables BDD_SCHEMA_ISOLATION=true with the foundation merged in PR #34. Achieves 2.85x speedup on the BDD test suite by running feature packages in parallel.
This is the proper architectural answer to the user's request 2026-05-03:
"Il faut pouvoir déclencher des tests BDD en parallèles pour que le projet puisse grandir et que sa taille n'ait pas trop d'impact sur l'expérience du développement."
Architecture
When BDD_SCHEMA_ISOLATION=true, each test PACKAGE (process) gets its own isolated PostgreSQL schema:
testserver.Start() generates a deterministic schema name from FEATURE env
CREATE SCHEMA <name> via the bootstrap repo
Open per-package gorm.DB with DSN search_path=<name>
AutoMigrate runs in the isolated schema (creates the users table)
Build per-package server.Server via server.NewServerWithUserRepo injecting the isolated repo + user service
Stop() drops the schema + closes the per-package pool
Packages then run in parallel (default Go test parallelism, -p ≈ NumCPU) without contention because each has its own schema + connection pool.
Why per-PACKAGE and not per-SCENARIO
The previous attempt (PR #26, reverted in PR #28) targeted per-scenario isolation but ran into:
Empty schemas (no migrations) causing 500 errors
The production server's repo was unaware of the testserver's schema
Per-package isolation is simpler and sufficient for parallel go test ./features/... because each test package runs in its own process. Per-scenario in-process isolation would require dynamic repo replacement mid-process — much more invasive and not needed for current scaling goals.
If we ever need per-scenario isolation, the building blocks are ready (NewPostgresRepositoryFromDSN + BuildSchemaIsolatedDSN from PR #34, NewServerWithUserRepo here, Exec helper here).
Changes
pkg/server/server.go: NEW factory NewServerWithUserRepo(cfg, ctx, userRepo, userService). Existing NewServer becomes a thin wrapper.
pkg/bdd/testserver/server.go: Start() takes the isolated path when BDD_SCHEMA_ISOLATION=true. Stop() cleans up.
pkg/user/postgres_repository.go: Exec(sql) helper for schema lifecycle.
scripts/run-bdd-tests.sh: -p 1 only when BDD_SCHEMA_ISOLATION!=true.
adr/0025-bdd-scenario-isolation-strategies.md: Status updated to Implemented.
Validation
5 consecutive runs of AuthBDD with isolation enabled:
Run 1: PASS
Run 2: PASS
Run 3: PASS
Run 4: PASS
Run 5: PASS
==> 5/5
public.users count after runs: 0 ← isolation confirmed
Local benchmark on the full features/... suite:
Mode
Time
CPU%
Sequential -p 1 (no isolation)
12.87s
80%
Parallel + isolation (this PR)
4.51s
311%
Speedup: 2.85x on the local 4-core dev machine. CI runners with more cores should see better.
Test plan
go build ./... PASS
go test ./pkg/... PASS
5/5 AuthBDD runs pass with isolation enabled
time go test ./features/... ≈ 4.5s with isolation vs 12.9s sequential
CI passes with BDD_SCHEMA_ISOLATION=true
Out of scope
Per-scenario isolation within a process (not needed for current scaling)
Auto-detect FEATURE name (currently relies on FEATURE env var, falls back to bdd)
🤖 Co-Authored-By: Claude Opus 4.7 (1M context)
## Summary
Re-enables `BDD_SCHEMA_ISOLATION=true` with the foundation merged in PR #34. Achieves **2.85x speedup** on the BDD test suite by running feature packages in parallel.
This is the proper architectural answer to the user's request 2026-05-03:
> "Il faut pouvoir déclencher des tests BDD en parallèles pour que le projet puisse grandir et que sa taille n'ait pas trop d'impact sur l'expérience du développement."
## Architecture
When `BDD_SCHEMA_ISOLATION=true`, each test PACKAGE (process) gets its own isolated PostgreSQL schema:
1. `testserver.Start()` generates a deterministic schema name from `FEATURE` env
2. `CREATE SCHEMA <name>` via the bootstrap repo
3. Open per-package `gorm.DB` with DSN `search_path=<name>`
4. `AutoMigrate` runs in the isolated schema (creates the `users` table)
5. Build per-package `server.Server` via `server.NewServerWithUserRepo` injecting the isolated repo + user service
6. `Stop()` drops the schema + closes the per-package pool
Packages then run in parallel (default Go test parallelism, `-p` ≈ NumCPU) without contention because each has its own schema + connection pool.
## Why per-PACKAGE and not per-SCENARIO
The previous attempt (PR #26, reverted in PR #28) targeted per-scenario isolation but ran into:
- Empty schemas (no migrations) causing 500 errors
- The production server's repo was unaware of the testserver's schema
Per-package isolation is **simpler and sufficient** for parallel `go test ./features/...` because each test package runs in its own process. Per-scenario in-process isolation would require dynamic repo replacement mid-process — much more invasive and not needed for current scaling goals.
If we ever need per-scenario isolation, the building blocks are ready (`NewPostgresRepositoryFromDSN` + `BuildSchemaIsolatedDSN` from PR #34, `NewServerWithUserRepo` here, `Exec` helper here).
## Changes
- `pkg/server/server.go`: NEW factory `NewServerWithUserRepo(cfg, ctx, userRepo, userService)`. Existing `NewServer` becomes a thin wrapper.
- `pkg/bdd/testserver/server.go`: `Start()` takes the isolated path when `BDD_SCHEMA_ISOLATION=true`. `Stop()` cleans up.
- `pkg/user/postgres_repository.go`: `Exec(sql)` helper for schema lifecycle.
- `scripts/run-bdd-tests.sh`: `-p 1` only when `BDD_SCHEMA_ISOLATION!=true`.
- `.gitea/workflows/ci-cd.yaml`: exports `BDD_SCHEMA_ISOLATION=true`.
- `adr/0025-bdd-scenario-isolation-strategies.md`: Status updated to **Implemented**.
## Validation
5 consecutive runs of AuthBDD with isolation enabled:
```
Run 1: PASS
Run 2: PASS
Run 3: PASS
Run 4: PASS
Run 5: PASS
==> 5/5
public.users count after runs: 0 ← isolation confirmed
```
Local benchmark on the full `features/...` suite:
| Mode | Time | CPU% |
|---|---|---|
| Sequential `-p 1` (no isolation) | **12.87s** | 80% |
| Parallel + isolation (this PR) | **4.51s** | 311% |
**Speedup: 2.85x** on the local 4-core dev machine. CI runners with more cores should see better.
## Test plan
- [x] `go build ./...` PASS
- [x] `go test ./pkg/...` PASS
- [x] 5/5 AuthBDD runs pass with isolation enabled
- [x] `time go test ./features/...` ≈ 4.5s with isolation vs 12.9s sequential
- [ ] CI passes with `BDD_SCHEMA_ISOLATION=true`
## Out of scope
- Per-scenario isolation within a process (not needed for current scaling)
- Auto-detect FEATURE name (currently relies on `FEATURE` env var, falls back to `bdd`)
🤖 Co-Authored-By: Claude Opus 4.7 (1M context)
Re-enables BDD_SCHEMA_ISOLATION=true with the foundation from PR #34
(NewPostgresRepositoryFromDSN). Achieves ~2.85x speedup on the BDD
test suite by running feature packages in parallel.
ARCHITECTURE
When BDD_SCHEMA_ISOLATION=true, each test package (process) gets its
own isolated PostgreSQL schema:
1. testserver.Start() generates a deterministic schema name per FEATURE
2. CREATE SCHEMA <name>
3. Open a per-package gorm.DB with DSN search_path=<name>
4. AutoMigrate runs in the isolated schema (creates users table)
5. Build a per-package server.Server with this isolated repo via
server.NewServerWithUserRepo
6. Stop() drops the schema + closes the per-package pool
Packages then run in parallel (default Go test parallelism) without
contention because each has its own schema + connection pool.
CHANGES
- pkg/server/server.go : NEW factory NewServerWithUserRepo(cfg, ctx,
userRepo, userService) that injects a per-test repo. Existing NewServer
becomes a thin wrapper.
- pkg/bdd/testserver/server.go : Start() chooses isolated mode based on
BDD_SCHEMA_ISOLATION env var. Stop() drops schema + closes pool.
- pkg/user/postgres_repository.go : Exec(sql) helper for the schema
lifecycle (CREATE/DROP) used by testserver.
- scripts/run-bdd-tests.sh : -p 1 only when BDD_SCHEMA_ISOLATION!=true.
When true, default Go parallelism (~ NumCPU packages concurrent).
- .gitea/workflows/ci-cd.yaml : exports BDD_SCHEMA_ISOLATION=true.
- adr/0025-bdd-scenario-isolation-strategies.md : Status to "Implemented".
VALIDATION
5x AuthBDD with isolation: 5/5 PASS, public.users count=0 after runs.
Local benchmark on the full features/... suite:
- Sequential -p 1 (no isolation): 12.87s
- Parallel + isolation (this PR): 4.51s
- Speedup: 2.85x
🤖 Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
Re-enables
BDD_SCHEMA_ISOLATION=truewith the foundation merged in PR #34. Achieves 2.85x speedup on the BDD test suite by running feature packages in parallel.This is the proper architectural answer to the user's request 2026-05-03:
Architecture
When
BDD_SCHEMA_ISOLATION=true, each test PACKAGE (process) gets its own isolated PostgreSQL schema:testserver.Start()generates a deterministic schema name fromFEATUREenvCREATE SCHEMA <name>via the bootstrap repogorm.DBwith DSNsearch_path=<name>AutoMigrateruns in the isolated schema (creates theuserstable)server.Serverviaserver.NewServerWithUserRepoinjecting the isolated repo + user serviceStop()drops the schema + closes the per-package poolPackages then run in parallel (default Go test parallelism,
-p≈ NumCPU) without contention because each has its own schema + connection pool.Why per-PACKAGE and not per-SCENARIO
The previous attempt (PR #26, reverted in PR #28) targeted per-scenario isolation but ran into:
Per-package isolation is simpler and sufficient for parallel
go test ./features/...because each test package runs in its own process. Per-scenario in-process isolation would require dynamic repo replacement mid-process — much more invasive and not needed for current scaling goals.If we ever need per-scenario isolation, the building blocks are ready (
NewPostgresRepositoryFromDSN+BuildSchemaIsolatedDSNfrom PR #34,NewServerWithUserRepohere,Exechelper here).Changes
pkg/server/server.go: NEW factoryNewServerWithUserRepo(cfg, ctx, userRepo, userService). ExistingNewServerbecomes a thin wrapper.pkg/bdd/testserver/server.go:Start()takes the isolated path whenBDD_SCHEMA_ISOLATION=true.Stop()cleans up.pkg/user/postgres_repository.go:Exec(sql)helper for schema lifecycle.scripts/run-bdd-tests.sh:-p 1only whenBDD_SCHEMA_ISOLATION!=true..gitea/workflows/ci-cd.yaml: exportsBDD_SCHEMA_ISOLATION=true.adr/0025-bdd-scenario-isolation-strategies.md: Status updated to Implemented.Validation
5 consecutive runs of AuthBDD with isolation enabled:
Local benchmark on the full
features/...suite:-p 1(no isolation)Speedup: 2.85x on the local 4-core dev machine. CI runners with more cores should see better.
Test plan
go build ./...PASSgo test ./pkg/...PASStime go test ./features/...≈ 4.5s with isolation vs 12.9s sequentialBDD_SCHEMA_ISOLATION=trueOut of scope
FEATUREenv var, falls back tobdd)🤖 Co-Authored-By: Claude Opus 4.7 (1M context)