d2d.emegrendeles.hu/tests/Feature/Deployment/DeploymentPackageBuilderTest.php
E98Developer 98cf955354 FIX DeploymentPackageTest felbontása hat fájlra a párhuzamos futtatáshoz
A paratest FÁJLONKÉNT osztja szét a munkát, ezért egyetlen 28 tesztes fájlból
nem tudott párhuzamosítani: egy processz vitte a teljes 137 mp-et, a másik öt
üresjáratban állt. A --parallel emiatt korábban egyenesen lassabb volt
(136 -> 143 mp), a teljes suite-on pedig csak 11%-ot hozott.

A felosztás témák szerint történt, de mért időkre kalibrálva, hogy egyik fájl
se domináljon (a leghosszabb a Builder, ~35 mp):

  AccessTest    6 teszt  ~7 mp   jogosultság, feature flag, 403
  GitTest       5 teszt ~18 mp   GitRepository, ChangeSetAnalyzer
  BuilderTest   9 teszt ~35 mp   csomagépítés, _TEENDOK, _torles.sh, verzió
  PageTest      4 teszt ~21 mp   commitlista, keresés, kiválasztás
  CreationTest  2 teszt ~32 mp   felületről indított csomagolás, kirakottnak jelölés
  DownloadTest  2 teszt ~25 mp   naplóbejegyzés, ZIP letöltés, útvonal-ellenőrzés

A két legdrágább teszt (21,7 és 20,4 mp) szándékosan külön fájlba került,
együtt hagyva ők adnák a padlót.

A közös segédfüggvények a DeploymentTestHelpers.php-ba kerültek. Ez nem
*Test.php, ezért a phpunit nem szedi fel teszt-fájlként. A minta-repót takarító
afterAll() helyére register_shutdown_function lépett: az afterAll fájlonként
futna le, és a következő fájl alól húzná ki a mintát.

Mért eredmény (6 mag): ezek a tesztek sorosan 137,00 mp, párhuzamosan
67,88 mp. Teljes suite párhuzamosan 149,78 -> 77,52 mp.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-17 10:48:31 +02:00

169 lines
6.7 KiB
PHP

<?php
use App\Services\Deployment\DeploymentPackageBuilder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;
require_once __DIR__.'/DeploymentTestHelpers.php';
uses(TestCase::class, RefreshDatabase::class);
beforeEach(function () {
Http::fake();
});
test('a teendők kérik a queue worker és a scheduler újraindítását, a cache ürítés után', function () {
deploymentAllowEnvironment();
$repository = deploymentTestRepository();
[$first, , $third] = $repository['commits'];
$package = app(DeploymentPackageBuilder::class)->build('d2d', 'test', $first, $third);
$teendok = File::get($package['path'].'/_TEENDOK.md');
expect($teendok)->toContain('docker service update --force d2d-environment_queue')
->and($teendok)->toContain('docker service update --force d2d-environment_scheduler')
// A 0 replikás scheduler miatt tudni kell, hogy a restart üresjárat lehet.
->and($teendok)->toContain('0 replikán fut');
// A restartnak a cache ürítés UTÁN kell jönnie: a frissen induló worker különben
// a régi, cache-elt konfigot töltené be.
expect(strpos($teendok, 'docker service update'))->toBeGreaterThan(strpos($teendok, 'config:clear'));
deploymentCleanup($repository['path']);
});
test('a queue worker nélküli környezetnél is kiderül, mit kell majd újraindítani', function () {
deploymentAllowEnvironment();
$repository = deploymentTestRepository();
[$first, , $third] = $repository['commits'];
$package = app(DeploymentPackageBuilder::class)->build('e2e', 'main', $first, $third);
$teendok = File::get($package['path'].'/_TEENDOK.md');
expect($teendok)->toContain('docker service update --force t2t_scheduler')
->and($teendok)->toContain('t2t_queue');
deploymentCleanup($repository['path']);
});
test('a teendők között szerepel a seeder futtatása a konkrét osztálynévvel', function () {
deploymentAllowEnvironment();
$repository = deploymentTestRepository();
[$first, , $third] = $repository['commits'];
$package = app(DeploymentPackageBuilder::class)->build('e2e', 'main', $first, $third);
$teendok = File::get($package['path'].'/_TEENDOK.md');
expect($teendok)->toContain('php artisan db:seed --class=TesztSeeder')
// A seeder puszta felmásolása nem futtatja le - ezt ki kell mondani.
->and($teendok)->toContain('NEM futtatja le')
// A Pennant purge feltételes: Eloquent mentésnél a FeatureFlagObserver elvégzi.
->and($teendok)->toContain('pennant:purge')
->and($teendok)->toContain('cache:clear');
deploymentCleanup($repository['path']);
});
test('a csomag a commitolt tartalmat viszi, nem a working tree állapotát', function () {
deploymentAllowEnvironment();
$repository = deploymentTestRepository();
[$first, , $third] = $repository['commits'];
// A working tree szándékos elrontása a commit után: ez nem kerülhet a csomagba.
File::put($repository['path'].'/app/Árlista.php', "<?php\n// EZ NEM KERÜLHET A CSOMAGBA\n");
$package = app(DeploymentPackageBuilder::class)->build('e2e', 'main', $first, $third);
expect(File::get($package['path'].'/app/Árlista.php'))->not->toContain('NEM KERÜLHET')
// A .gitattributes eol=lf miatt a git archive LF-fel ír, Windowson is.
->and(File::get($package['path'].'/app/Árlista.php'))->not->toContain("\r\n");
deploymentCleanup($repository['path']);
});
test('a csomagból kimarad a kizárt és a kézzel kivett fájl, a törlendők külön listára kerülnek', function () {
deploymentAllowEnvironment();
$repository = deploymentTestRepository();
[$first, , $third] = $repository['commits'];
$package = app(DeploymentPackageBuilder::class)->build('e2e', 'main', $first, $third, ['app/Elso.php']);
expect(File::exists($package['path'].'/app/Atnevezett.php'))->toBeTrue()
->and(File::exists($package['path'].'/app/Elso.php'))->toBeFalse()
->and(File::exists($package['path'].'/.env'))->toBeFalse()
->and(File::exists($package['path'].'/app/Regi.php'))->toBeFalse()
->and($package['counts']['skipped'])->toBe(1)
->and($package['counts']['missing'])->toBe(0);
$torlendo = File::get($package['path'].'/_TORLENDO.txt');
expect($torlendo)->toContain('app/Regi.php')
->and($torlendo)->toContain('app/Atnevezendo.php');
deploymentCleanup($repository['path']);
});
test('a csomag rögzíti a kirakott verziót', function () {
deploymentAllowEnvironment();
$repository = deploymentTestRepository();
[$first, , $third] = $repository['commits'];
$package = app(DeploymentPackageBuilder::class)->build('e2e', 'main', $first, $third);
$version = json_decode(File::get($package['path'].'/public/deploy-version.json'), true);
expect($version['commit'])->toBe($third)
->and($version['target'])->toBe('e2e')
->and($version['branch'])->toBe('main');
deploymentCleanup($repository['path']);
});
test('a limit fölötti fájlszámnál nem készül csomag', function () {
deploymentAllowEnvironment();
$repository = deploymentTestRepository();
[$first, , $third] = $repository['commits'];
Config::set('deployment.max_files', 1);
expect(fn () => app(DeploymentPackageBuilder::class)->build('e2e', 'main', $first, $third))
->toThrow(RuntimeException::class);
expect(File::exists(config('deployment.output_path')))->toBeFalse();
deploymentCleanup($repository['path']);
});
test('a csomagoló szerveren akkor sem indul el, ha közvetlenül hívják', function () {
deploymentAllowEnvironment();
$repository = deploymentTestRepository();
[$first, , $third] = $repository['commits'];
Config::set('app.stage', 'PROD');
expect(fn () => app(DeploymentPackageBuilder::class)->build('e2e', 'main', $first, $third))
->toThrow(RuntimeException::class);
deploymentCleanup($repository['path']);
});
test('a törlő szkript dry runban fut és ellenőrzi az app gyökeret', function () {
deploymentAllowEnvironment();
$repository = deploymentTestRepository();
[$first, , $third] = $repository['commits'];
$package = app(DeploymentPackageBuilder::class)->build('e2e', 'main', $first, $third);
$script = File::get($package['path'].'/_torles.sh');
expect($script)->toStartWith('#!/usr/bin/env bash')
->and($script)->toContain('[[ -f artisan && -d app ]]')
->and($script)->toContain('"app/Regi.php"')
// Windowson generáljuk, Linuxon fut: CRLF-fel a shebang sor törne el.
->and($script)->not->toContain("\r\n");
deploymentCleanup($repository['path']);
});