Testing Guidelines
Test Pyramid
- Unit tests (fast, many): domain aggregates, value objects, handlers
- Integration tests (medium, some): repositories, API endpoints, event handlers
- E2E tests (slow, few): critical user flows
Directory Structure
tests/
├── Unit/
│ └── Module/{ModuleName}/
│ ├── Domain/
│ │ └── Model/{Aggregate}Test.php
│ └── Application/
│ └── Command/{Handler}Test.php
├── Integration/
│ └── Module/{ModuleName}/
│ ├── Infrastructure/
│ │ └── Persistence/{Repository}Test.php
│ └── Presentation/
│ └── Controller/{Controller}Test.php
└── Fixtures/
└── {ModuleName}/
└── {Fixture}Fixture.php
Unit Tests
- No database, no framework kernel, no external services
- Test aggregate creation, state transitions, invariant violations
- Test value object validation and equality
- Test command handlers with mocked repositories
- Use PHPUnit data providers for edge cases
Integration Tests
- Use Symfony’s
WebTestCase or KernelTestCase
- Real database (test database, reset between tests)
- Use fixtures for test data setup
- Test full request/response cycle for API endpoints
- Assert: status code, response structure, database state
Naming
- Test classes:
{ClassUnderTest}Test
- Test methods:
test_{what_is_being_tested}_{expected_outcome}
- Example:
test_create_member_with_valid_data_succeeds
- Example:
test_create_member_without_email_throws_exception
Assertions
- Be specific: assert exact values, not just “not null”
- Assert side effects: events dispatched, database state changed
- Assert error cases: correct exception type and message
- Assert tenant scoping: data from other tenants is not returned
What to Test
- Every aggregate: creation, state transitions, invariant violations
- Every command handler: happy path + validation failures
- Every API endpoint: success, validation error, auth required, not found
- Event emission: correct events with correct payload
- Privacy: privacy settings respected in queries
What NOT to Test
- Getter/setter boilerplate
- Framework internals
- Third-party library behavior
- Private methods (test through public API)