Steuerkram/tests/run.php

153 lines
5 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env php
<?php
declare(strict_types=1);
/**
* Steuerkram Test-Runner
*
* Führt alle Tests im tests/-Verzeichnis aus und gibt eine Zusammenfassung aus.
* Exit-Code: 0 = alle Tests bestanden, 1 = mindestens ein Fehler.
*
* Verwendung:
* php tests/run.php
* php tests/run.php --json # Ausgabe als JSON (für Skript-Auswertung)
*/
$projectRoot = dirname(__DIR__);
$autoload = $projectRoot . '/vendor/autoload.php';
if (!file_exists($autoload)) {
fwrite(STDERR, "Fehler: vendor/autoload.php nicht gefunden. Bitte 'composer install' ausführen.\n");
exit(1);
}
require $autoload;
require __DIR__ . '/TestCase.php';
\Steuerkram\Config::load();
$jsonMode = in_array('--json', $argv ?? [], true);
TestCase::setQuiet($jsonMode);
// PHP-Warnungen/-Notices einzelner Tests (z. B. absichtlich provozierte
// Fehlerfälle) dürfen die JSON-Ausgabe auf STDOUT nicht verunreinigen –
// scripts/container/run-tests.sh wertet sie sonst nicht mehr auswertbar aus.
if ($jsonMode) {
ini_set('display_errors', 'stderr');
}
/**
* Erfasst den Bestand unterhalb der Datenverzeichnisse.
*
* Ein Vergleich vor/nach dem Lauf deckt Rückstände auf, die ein Test nicht über
* TestCase::registerTempPath() angemeldet hat. Solche Reste sind gefährlich,
* weil der Rollback die Belegnummer wieder freigibt: ein späterer echter Upload
* trifft dann auf ein bereits existierendes Verzeichnis.
*/
function datenBestand(): array
{
$bestand = [];
foreach ([\Steuerkram\Config::get('upload_dir'), \Steuerkram\Config::get('logo_dir')] as $root) {
if (!is_string($root) || !is_dir($root)) continue;
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($root, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::SELF_FIRST
);
foreach ($iterator as $entry) {
$bestand[$entry->getPathname()] = true;
}
}
return $bestand;
}
/**
* Liefert die neu hinzugekommenen Pfade, ohne deren Unterpfade (sonst meldet
* ein neues Verzeichnis auch jede darin liegende Datei einzeln).
*/
function neuePfade(array $vorher, array $nachher): array
{
$neu = array_keys(array_diff_key($nachher, $vorher));
sort($neu);
$oberste = [];
foreach ($neu as $pfad) {
foreach ($oberste as $bekannt) {
if (str_starts_with($pfad, $bekannt . '/')) continue 2;
}
$oberste[] = $pfad;
}
return $oberste;
}
// Alle Test-Dateien laden
$testFiles = glob(__DIR__ . '/[0-9][0-9]_*.php');
sort($testFiles);
$testClasses = [];
foreach ($testFiles as $file) {
require_once $file;
// Klassenname aus Dateiname ableiten: 01_BelegUploadTest.php → BelegUploadTest
$base = basename($file, '.php');
$className = preg_replace('/^\d+_/', '', $base);
if (class_exists($className)) {
$testClasses[] = $className;
}
}
if (empty($testClasses)) {
fwrite(STDERR, "Keine Testklassen gefunden.\n");
exit(1);
}
if (!$jsonMode) {
echo "\n\e[1m╔══════════════════════════════════════════╗\e[0m\n";
echo "\e[1m║ Steuerkram Test-Suite ║\e[0m\n";
echo "\e[1m╚══════════════════════════════════════════╝\e[0m\n";
}
$allFailures = [];
$dataVorher = datenBestand();
foreach ($testClasses as $class) {
/** @var TestCase $test */
$test = new $class();
$failures = $test->execute();
$allFailures = array_merge($allFailures, $failures);
}
$summary = TestCase::globalSummary();
$rueckstaende = neuePfade($dataVorher, datenBestand());
if (!$jsonMode) {
$total = $summary['passed'] + $summary['failed'];
echo "\n\e[1m══════════════════════════════════════════\e[0m\n";
if ($summary['failed'] === 0) {
echo "\e[32;1m✓ Alle {$summary['passed']} Tests bestanden.\e[0m\n";
} else {
echo "\e[31;1m✗ {$summary['failed']} von {$total} Tests fehlgeschlagen:\e[0m\n";
foreach ($summary['failures'] as $failure) {
echo " • {$failure}\n";
}
}
echo "\e[1m══════════════════════════════════════════\e[0m\n";
if ($rueckstaende) {
echo "\n\e[33mHinweis: Der Testlauf hat Dateien in den Datenverzeichnissen hinterlassen:\e[0m\n";
foreach ($rueckstaende as $pfad) {
echo " • {$pfad}\n";
}
echo " Der zuständige Test sollte den Pfad über \e[1m\$this->registerTempPath()\e[0m anmelden.\n";
}
echo "\n";
} else {
echo json_encode([
'passed' => $summary['passed'],
'failed' => $summary['failed'],
'failures' => $summary['failures'],
], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
echo "\n";
}
exit($summary['failed'] > 0 ? 1 : 0);