115 lines
3.3 KiB
PHP
115 lines
3.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
/**
|
|
* Basis-Testklasse für Steuerkram-Tests.
|
|
*
|
|
* Jeder Test läuft in einer MySQL-Transaktion, die am Ende zurückgerollt wird.
|
|
* Damit bleibt die Datenbank nach dem Test unverändert.
|
|
*/
|
|
abstract class TestCase
|
|
{
|
|
private static int $totalPassed = 0;
|
|
private static int $totalFailed = 0;
|
|
private static array $allFailures = [];
|
|
|
|
protected int $passed = 0;
|
|
protected int $failed = 0;
|
|
protected array $failures = [];
|
|
protected string $testName = '';
|
|
|
|
abstract public function run(): void;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
\Steuerkram\Database::beginTransaction();
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
try {
|
|
\Steuerkram\Database::rollBack();
|
|
} catch (\Throwable) {
|
|
// Transaktion war evtl. nicht aktiv
|
|
}
|
|
}
|
|
|
|
protected function assert(bool $condition, string $message): void
|
|
{
|
|
if ($condition) {
|
|
$this->passed++;
|
|
echo " \e[32m✓\e[0m {$message}\n";
|
|
} else {
|
|
$this->failed++;
|
|
$this->failures[] = "[{$this->testName}] {$message}";
|
|
echo " \e[31m✗\e[0m {$message}\n";
|
|
}
|
|
}
|
|
|
|
protected function assertEquals(mixed $expected, mixed $actual, string $message): void
|
|
{
|
|
$this->assert(
|
|
$expected == $actual,
|
|
"{$message} (erwartet: " . json_encode($expected) . ", erhalten: " . json_encode($actual) . ")"
|
|
);
|
|
}
|
|
|
|
protected function assertGreaterThan(int $min, mixed $actual, string $message): void
|
|
{
|
|
$this->assert($actual > $min, "{$message} (Wert: {$actual}, muss > {$min})");
|
|
}
|
|
|
|
protected function assertNotEmpty(mixed $value, string $message): void
|
|
{
|
|
$this->assert(!empty($value), $message);
|
|
}
|
|
|
|
/**
|
|
* Liefert Konto-ID anhand der Kontonummer oder null wenn nicht gefunden.
|
|
*/
|
|
protected function findAccountId(string $kontonummer): ?int
|
|
{
|
|
$row = \Steuerkram\Database::fetchOne(
|
|
'SELECT id FROM accounts WHERE kontonummer = ?',
|
|
[$kontonummer]
|
|
);
|
|
return $row ? (int)$row['id'] : null;
|
|
}
|
|
|
|
public function execute(): array
|
|
{
|
|
echo "\n\e[1m{$this->testName}\e[0m\n";
|
|
$this->setUp();
|
|
try {
|
|
$this->run();
|
|
} catch (\Throwable $e) {
|
|
$this->failed++;
|
|
$msg = "[{$this->testName}] Ausnahme: " . $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine();
|
|
$this->failures[] = $msg;
|
|
echo " \e[31m✗\e[0m Unerwartete Ausnahme: " . $e->getMessage() . "\n";
|
|
} finally {
|
|
$this->tearDown();
|
|
}
|
|
|
|
$status = $this->failed === 0
|
|
? "\e[32mBestanden ({$this->passed}/{$this->passed})\e[0m"
|
|
: "\e[31m{$this->failed} Fehler, {$this->passed} OK\e[0m";
|
|
echo " → {$status}\n";
|
|
|
|
self::$totalPassed += $this->passed;
|
|
self::$totalFailed += $this->failed;
|
|
self::$allFailures = array_merge(self::$allFailures, $this->failures);
|
|
|
|
return $this->failures;
|
|
}
|
|
|
|
public static function globalSummary(): array
|
|
{
|
|
return [
|
|
'passed' => self::$totalPassed,
|
|
'failed' => self::$totalFailed,
|
|
'failures' => self::$allFailures,
|
|
];
|
|
}
|
|
}
|