Test Naming Conventions
debt(d7/e1/b3/t5)
Closest to 'only careful code review or runtime testing' (d7). The detection_hints specify automated=no, and while phpunit/pest are listed as tools, they do not automatically flag poor naming conventions — no linter rule catches 'testGetUser()' as insufficiently descriptive. Only a human reviewer reading the test output or conducting a code review will notice the names are non-actionable.
Closest to 'one-line patch or single-call swap' (e1). The quick_fix is purely a rename: change testGetUser() to test_it_returns_user_for_valid_id(). Each fix is a single identifier rename per test method, requiring no structural code changes.
Closest to 'localised tax' (b3). Poor naming applies within the test suite only — the test files themselves carry the cost (harder to diagnose failures), but production code and other components are unaffected. It is a persistent readability tax on the test layer, but the rest of the codebase is not shaped by it.
Closest to 'notable trap (a documented gotcha most devs eventually learn)' (t5). The misconception is explicit: developers naturally believe naming the method under test (testCalculateTotal) is sufficient. The trap is that the name describes implementation rather than scenario/behaviour, so a failing test gives zero diagnostic signal. This is a well-known testing gotcha that most developers encounter and learn over time, but it's not obvious to beginners.
Also Known As
TL;DR
Explanation
PHPUnit test methods should describe the scenario being tested, not the method under test. Pattern: testMethodName is poor (what scenario?); testUserCannotLoginWithWrongPassword is good (describes behaviour). BDD-style: it_rejects_login_with_wrong_password or givenActiveUser_whenWrongPassword_thenAccessDenied (Given/When/Then). The test name should make the failure message self-explanatory — if it fails you know exactly what broke without reading the test body.
Common Misconception
Why It Matters
Common Mistakes
- test + method name: testGetUser() — what scenario? What input? What expected outcome?
- Overly generic names: testHappyPath(), testEdgeCase() — not descriptive.
- Not using @test annotation with natural language: /** @test */ public function user_cannot_login_with_wrong_password().
- Names that describe implementation: testCallsDatabaseQueryOnce() — describe behaviour, not internals.
Code Examples
// Useless test names — failures are opaque:
public function testCalculate(): void { /* What calculation? What case? */ }
public function testUser(): void { /* What about a user? */ }
public function testHappyPath(): void { /* Every test is a happy path */ }
public function testGetUserById(): void { /* What scenario? Exists? Missing? */ }
// Self-documenting test names:
public function testCalculateTotalAppliesVatCorrectlyForUkCustomers(): void { }
public function testGuestUserCannotAccessAdminPanel(): void { }
public function testOrderStatusChangesToProcessingAfterPaymentConfirmed(): void { }
public function testFindByIdReturnsNullWhenUserDoesNotExist(): void { }
// Or BDD-style with @test:
/** @test */
public function it_rejects_checkout_when_cart_is_empty(): void { }