Skip to content

Build1 publisher3 min readPublished

The guard that worked in tests and still wrote 2,684 live records

A test-environment check asked which process it was running in. The write it was supposed to block happened in a different process, once per headless login, for about a year.

The Engineer · Build desk

Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

What happened

  • A developer found 2,684 junk records in a live third-party app, all created by his own test suite over roughly a year, through a guard written specifically to prevent that.
  • When a user logs into the app for the first time, the app mints a record for them in its help desk: a real record in a real third-party system, created over a real HTTP call.
  • The test suite creates and destroys hundreds of users per suite run.
  • The guard isTest() returned true if class_exists("TestClass", false) succeeded; TestClass is the test factory declared by tests/bootstrap.php.
  • isTest() cached only a positive result, because TestClass is defined after start.php runs and an early call must not memoize false.

Compiled by The EngineerSomething wrong?How this is made

Why it matters

A developer writing on dev.to found 2,684 junk records in a live third-party help desk, every one created by his own test suite over roughly a year, and every one waved through by a guard written specifically to prevent that [1]. The guard was correct and demonstrable in tests [7]; it asked which process it was running in, while the write it was meant to block happened in a different process [10][11].

The behaviour being guarded is ordinary. When a user logs in for the first time, the app mints a record for them in the help desk: a real record in a real third-party system, over a real HTTP call [2]. Useful once, in production. Ruinous in a suite that creates and destroys hundreds of users per run [3].

The guard was a function called isTest(), which returned true when class_exists("TestClass", false) found the test factory declared by tests/bootstrap.php [4]. It cached only positive results, because TestClass is defined after start.php runs and an early call must not memoise false [5]. The call site checked it and returned early [6]. Write a test that creates a user, assert no HTTP call leaves the box, and it passes [7].

The hole is in the browser tests. Twenty-four test files drive headless Chrome against the actual dev server, and fourteen of them log in by filling out the real /login form and submitting it [8][9]. That login is an HTTP request handled by php-fpm, a separate process that was already running before the suite existed; tests/bootstrap.php never loaded there, so TestClass was never declared and class_exists returned false [10]. Every headless login minted a live record [11]. Fourteen tests, several suite runs a day, about a year, 2,684 records [12]. That averages roughly seven records a day, or about 192 per login test [20][21].

The distinction the author draws is the useful part. A process-scoped guard, whether class_exists, a global flag set at bootstrap, an env var, or defined('PHPUNIT_RUNNING'), is cheap and precise and stops dead at the process boundary: anything you spawn, fork, queue, or request over HTTP is outside its knowledge [13]. A data-scoped guard asks about the subject instead. Test users have addresses at a dedicated domain, and that domain travels in the POST body through nginx into php-fpm, into the session, into the queue payload, into the daemon that picks the job up the next morning, because it is the request [14]. The implementation is a stripos check for "@test.example.com" [15].

The fix kept both. wantHelpDeskRecord() takes the email address; inside PHPUnit it defers to a static opt-in flag on TestClass, and outside it checks whether the address is a test address [16]. Exactly one test opts in, creates a real record, asserts its fields, and deletes it, which keeps the live integration covered instead of mocked into meaninglessness [17]. The call site now passes the subject in [18].

Worth checking in your own tree: the author's suggested test is not whether a guard is correct but how far it travels [19]. Grep for guards that read ambient state, then trace every path where the guarded code can run somewhere your bootstrap never loaded [19]. Browser and end-to-end suites are the obvious case, and the one that caught him [9][10].

Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories