- Follow Arrange-Act-Assert pattern in all test methods.
- Name tests descriptively: `it_returns_404_when_user_not_found` or `testUserCreationWithInvalidEmail`.
- Use PHPUnit's `@dataProvider` for parameterized tests and `setUp()`/`tearDown()` for test fixtures — mock dependencies with Mockery or Prophecy.
- Use data providers for parameterized tests — test multiple input/output combinations without duplicating test logic.
- Mock dependencies through interfaces — prefer interface-based mocking for loose coupling.
- Use database isolation for tests that modify state — reset to a clean state between tests.
- Test edge cases: empty inputs, null values, permission boundaries, and error responses.