CI Test Strategy
CI Test Strategy
Section titled “CI Test Strategy”We want CI to give developers fast, reliable feedback without slowing them down.
- Faster PR cycles: developers stay in flow instead of context-switching during long CI runs
- Catch regressions before production: targeted tests on PRs plus a full suite running on a schedule
- Reduce PR aging: shorter CI means PRs get reviewed and merged sooner
We split CI into two complementary layers.
PR CI runs Pint, PHPStan, unit tests, architecture tests, Livewire checks, and only the feature/CPC tests related to changed files, targeting 2-5 minutes per run.
The scheduled full suite runs all tests (unit, feature, CPC, and browser) every 3 hours on main during work hours (7 AM UTC - 7 PM PST), acting as a safety net to catch anything the targeted PR runs might miss.
- On failure: creates a GitHub issue with the failed tests and JUnit output (labeled for standup triage) and sends a Discord notification with pass/fail status, test counts, duration, and a link to the run.
- On success: sends a Discord notification confirming the suite is green.
How We Keep Tests Fast
Section titled “How We Keep Tests Fast”Neither unit nor feature tests hit the database. That’s what makes the 2-5 minute PR CI target possible.
- Unit tests test individual components in complete isolation. No database, no external services, no framework boot. They validate that a single class or method behaves correctly on its own.
- Feature tests verify that components, services, and actions work together, but mock the data layer instead of hitting the database.
Database-dependent tests (browser tests, full integration tests) run only in the scheduled full suite.
What Runs on Every PR
Section titled “What Runs on Every PR”- Pint: code style enforcement
- PHPStan: static analysis
- Architecture tests: DDD boundary enforcement
- Unit tests: fast, isolated, no database
- Feature tests: no database, mapped from changed files (see mapping below)
- Livewire check: unused components
Changed-File-to-Test Mapping
Section titled “Changed-File-to-Test Mapping”| Changed path pattern | Test directories to run |
|---|---|
app/{Domain}/ (e.g. app/Buildings/) |
tests/Feature/{Domain}/, matching tests/CPC/ subdirs |
app/Http/Controllers/{Area} |
tests/Feature/Http/ + related domain dirs |
app/Livewire/{Area} |
tests/Feature/Livewire/ + tests/CPC/Livewire/ matching subdirs |
tests/Feature/{Dir}/ or tests/CPC/{Dir}/ |
Those directories directly |
resources/views/livewire/{area} |
Corresponding Livewire test dirs |
Cross-cutting changes fall back to the full Feature + CPC suite: app/Models/, app/Middleware/, app/Providers/, config/, database/migrations/, routes/, composer.*
Why File-to-Test Mapping Works
Section titled “Why File-to-Test Mapping Works”Momentum follows a Domain-Driven Design (DDD) structure. Each domain is self-contained under app/, with its own models, services, and actions. The test suite mirrors this, tests/Feature/{Domain}/ and tests/CPC/{Domain}/ map directly to their source counterparts.
When you change files within a single domain, CI runs only that domain’s tests. Cross-cutting concerns (models, middleware, providers, routes, migrations) sit outside domain boundaries, so changes there trigger the full suite.
