From 947eccff90c903ebb2a61885eb92af61f6394930 Mon Sep 17 00:00:00 2001 From: E98Developer Date: Mon, 17 Aug 2026 10:34:13 +0200 Subject: [PATCH] =?UTF-8?q?FIX=20Teszt=20p=C3=A1rhuzamos=20futtat=C3=A1s?= =?UTF-8?q?=20processzenk=C3=A9nti=20adatb=C3=A1zissal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A --parallel eddig két okból nem működött volna: 1. A setUp() a parent::setUp() ELŐTT hívja a refreshApplication()-t, hogy a DB nevét a RefreshDatabase előtt ellenőrizhesse. A Laravel viszont a ParallelTesting::callSetUpTestCaseCallbacks()-ot csak az "if (! $this->app)" ágban futtatja (InteractsWithTestCaseLifecycle), ami így kimaradt - a processzenkénti adatbázis sosem jött létre, minden processz a közös d2dTest-et migrálta volna egyszerre. A callbacket most magunk hívjuk meg; nem párhuzamos futásnál no-op. 2. A névellenőrzés pontos "d2dtest" egyezést várt, és eltérésnél nem hibát dobott, hanem VISSZAÍRTA a configot d2dTest-re - vagyis csendben közös adatbázisra terelte volna a processzeket. A név mostantól a /^d2dtest(_test_\d+)?$/ mintát követi, ami a Laravel TestDatabases::testDatabase() elnevezését fedi le. Szándékosan nem str_starts_with($db, 'd2d'): az átengedné az éles adatbázist is. Az éles d2d elleni azonnali exit(1) változatlan. Ellenőrizve: tiszta lapról a párhuzamos futás létrehozta a d2dtest_test_1..6 adatbázisokat, a sima futás változatlanul működik. Co-Authored-By: Claude Opus 5 --- tests/TestCase.php | 51 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 8 deletions(-) diff --git a/tests/TestCase.php b/tests/TestCase.php index 4f6d74a..e8eb01f 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -3,6 +3,7 @@ namespace Tests; use Illuminate\Foundation\Testing\TestCase as BaseTestCase; +use Illuminate\Support\Facades\ParallelTesting; abstract class TestCase extends BaseTestCase { @@ -10,14 +11,34 @@ protected function setUp(): void { if (! $this->app) { $this->refreshApplication(); + + // A Laravel ezt a saját setUp()-jában csak akkor hívja meg, ha ŐT hozta létre az + // alkalmazást (InteractsWithTestCaseLifecycle: "if (! $this->app)"). Mi viszont + // előbb bootolunk - hogy a DB nevét a RefreshDatabase ELŐTT ellenőrizhessük -, + // ezért ott az az ág kimaradna, és a --parallel processzenkénti adatbázisa sosem + // jönne létre: minden processz a közös d2dTest-et migrálná egyszerre. + // Nem párhuzamos futásnál ez no-op (whenRunningInParallel). + ParallelTesting::callSetUpTestCaseCallbacks($this); } - $currentDb = config('database.connections.mysql.database'); - $currentEnv = env('APP_ENV'); + $this->guardTestDatabase(); + + parent::setUp(); + } + + /** + * Megakadályozza, hogy a tesztek az éles adatbázison fussanak. + * + * A parent::setUp() ELŐTT kell lefutnia: a RefreshDatabase feltétel nélkül eldobja + * a táblákat, tehát utólag ellenőrizni már késő lenne. + */ + private function guardTestDatabase(): void + { + $database = (string) config('database.connections.mysql.database'); // SZIGORÚ ELLENŐRZÉS: A 'd2d' adatbázist SOHA nem szabad teszthez használni! // Akkor is védünk, ha a config cache-elve van vagy az APP_ENV nem 'testing'. - if (strtolower($currentDb) === 'd2d') { + if (strtolower($database) === 'd2d') { echo "\n\n!!! KRITIKUS BIZTONSÁGI HIBA !!!\n"; echo "A tesztek az ÉLŐ (d2d) adatbázishoz kapcsolódnak!\n"; echo "Ez az adatbázis törléséhez (RefreshDatabase) vezetne.\n"; @@ -26,17 +47,31 @@ protected function setUp(): void exit(1); } + if (env('APP_ENV') !== 'testing') { + return; + } + // Kényszerítsük a teszt adatbázist, ha testing környezetben vagyunk és nem d2d - if ($currentEnv === 'testing' && strtolower($currentDb) !== 'd2dtest') { + if (! $this->isTestDatabase($database)) { config(['database.connections.mysql.database' => 'd2dTest']); - $currentDb = 'd2dTest'; + $database = (string) config('database.connections.mysql.database'); } // Általános ellenőrzés, hogy a teszt adatbázis legyen használva - if (strtolower($currentDb) !== 'd2dtest' && $currentEnv === 'testing') { - throw new \Exception('HIBA: A teszteknek a d2dTest adatbázison kellene futniuk. Aktuális konfiguráció: ' . $currentDb . '. Kérlek futtasd a "php artisan config:clear" parancsot!'); + if (! $this->isTestDatabase($database)) { + throw new \Exception('HIBA: A teszteknek a d2dTest adatbázison kellene futniuk. Aktuális konfiguráció: '.$database.'. Kérlek futtasd a "php artisan config:clear" parancsot!'); } + } - parent::setUp(); + /** + * Elfogadható a 'd2dTest', illetve a --parallel processzenkénti 'd2dTest_test_1' alakja + * (a nevet a Laravel adja: TestDatabases::testDatabase() -> "{$database}_test_{$token}"). + * + * Szándékosan NEM egyszerű prefix-vizsgálat: a kézenfekvő str_starts_with($db, 'd2d') + * átengedné az éles 'd2d' nevet is. + */ + private function isTestDatabase(string $database): bool + { + return preg_match('/^d2dtest(_test_\d+)?$/', strtolower($database)) === 1; } }