dbxapp 4.1.3
CMS, Shop, Workflows und modulare Geschäftsanwendungen
Loading...
Searching...
No Matches
dbxSelfTestRunner_test.php
Go to the documentation of this file.
1<?php
2require_once dirname(__DIR__) . '/include/dbxSelfTestRunner.class.php';
3
5
6function selftest_assert(bool $condition, string $message): void {
7 if (!$condition) {
8 fwrite(STDERR, "FAIL: {$message}\n");
9 exit(1);
10 }
11}
12
13function selftest_remove_tree(string $path): void {
14 if (!is_dir($path)) return;
15 $iterator = new RecursiveIteratorIterator(
16 new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS),
17 RecursiveIteratorIterator::CHILD_FIRST
18 );
19 foreach ($iterator as $item) {
20 if ($item->isDir()) rmdir($item->getPathname());
21 else unlink($item->getPathname());
22 }
23 rmdir($path);
24}
25
26$fixture = sys_get_temp_dir() . '/dbx-selftest-runner-' . bin2hex(random_bytes(4));
27$testDir = $fixture . '/dbx/modules/demo/tests';
28$logDir = $fixture . '/files/sys/selftest';
29mkdir($testDir, 0777, true);
30mkdir($logDir, 0777, true);
31file_put_contents(
32 $testDir . '/demo_test.php',
33 "<?php if (getenv('DBX_SELFTEST') !== '1') { fwrite(STDERR, 'FAIL missing test context'); exit(9); } echo 'PASS demo';\n"
34);
35file_put_contents($testDir . '/demo_test.js', "console.log('PASS browser demo');\n");
36
37try {
38 $runner = new dbxSelfTestRunner($fixture, $logDir);
39 $runnerSource = (string)file_get_contents(dirname(__DIR__) . '/include/dbxSelfTestRunner.class.php');
40 $controllerSource = (string)file_get_contents(dirname(__DIR__) . '/include/dbxSelfTestController.class.php');
41 $dashboardSource = (string)file_get_contents(dirname(__DIR__) . '/tpl/js/selftest.js');
42 selftest_assert(str_contains($runnerSource, "array(\$php, '-n', '-l', \$file)"), 'PHP-Syntaxchecks muessen ohne php.ini-Startkosten laufen.');
43 selftest_assert(str_contains($controllerSource, '@set_time_limit(360)'), 'Lange Web-Systemtests brauchen ein kontrolliertes Request-Zeitlimit.');
44 selftest_assert(str_contains($dashboardSource, 'runningTestId') && str_contains($dashboardSource, 'response.text()'), 'Das Dashboard muss Aktivitaet und nicht-JSON Serverfehler aussagekraeftig behandeln.');
45 $startFunction = strpos($dashboardSource, 'async function startRun(profile, ids)');
46 $busyGuard = $startFunction === false ? false : strpos($dashboardSource, 'if (state.busy) return;', $startFunction);
47 $busyLock = $busyGuard === false ? false : strpos($dashboardSource, 'setBusy(true);', $busyGuard);
48 $startRequest = $busyLock === false ? false : strpos($dashboardSource, 'request(urls.start', $busyLock);
50 $startFunction !== false && $busyGuard !== false && $busyLock !== false && $startRequest !== false && $busyLock < $startRequest,
51 'Startschaltflaechen muessen vor dem ersten Request gegen Doppelklicks gesperrt werden.'
52 );
53 $phpResolver = new ReflectionMethod($runner, 'resolvePhpCliBinary');
55 selftest_assert(is_string($phpCli) && is_file($phpCli), 'Ein echter PHP-CLI-Interpreter muss aufgeloest werden.');
56 selftest_assert((bool)preg_match('/^php(?:\.exe)?$/i', basename($phpCli)), 'Apache/httpd darf nicht als PHP-CLI verwendet werden.');
57 $catalog = $runner->catalog('full');
58 $demo = array_values(array_filter($catalog, static fn(array $test): bool => ($test['relative_path'] ?? '') === 'dbx/modules/demo/tests/demo_test.php'));
59 $browserDemo = array_values(array_filter($catalog, static fn(array $test): bool => ($test['relative_path'] ?? '') === 'dbx/modules/demo/tests/demo_test.js'));
60 selftest_assert(count($catalog) >= 8, 'Systemtests und Fixture-Test muessen entdeckt werden.');
61 selftest_assert(count($demo) === 1, 'PHP-Test muss genau einmal im Katalog stehen.');
62 selftest_assert(count($browserDemo) === 1 && $browserDemo[0]['execution'] === 'browser', 'JavaScript-Test muss fuer den Browser katalogisiert werden.');
63
64 $run = $runner->startRun('full', array($demo[0]['id']), 'single');
65 $result = $runner->executeRunTest($run['id'], $demo[0]['id']);
66 selftest_assert($result['status'] === 'passed', 'Einzeltest muss isoliert erfolgreich laufen.');
67 $finished = $runner->finishRun($run['id']);
68 selftest_assert($finished['status'] === 'passed', 'Abgeschlossener Lauf muss bestanden sein.');
69 selftest_assert(($finished['totals']['passed'] ?? 0) === 1, 'Summen muessen das Ergebnis enthalten.');
70 selftest_assert(is_file((string)$runner->runLogPath($run['id'])), 'JSON-Protokoll muss geschrieben werden.');
71 selftest_assert($runner->loadRun('../ungueltig') === null, 'Ungueltige Lauf-IDs duerfen nicht aufgeloest werden.');
72
73 $browserRun = $runner->startRun('full', array($browserDemo[0]['id']), 'single');
74 $browserResult = $runner->recordBrowserTestResult($browserRun['id'], $browserDemo[0]['id'], array(
75 'status' => 'passed',
76 'output' => 'PASS browser demo',
77 'duration_ms' => 12,
78 ));
79 selftest_assert($browserResult['status'] === 'passed' && $browserResult['execution'] === 'browser', 'Browserergebnis muss validiert protokolliert werden.');
80 selftest_assert($runner->finishRun($browserRun['id'])['status'] === 'passed', 'Browser-Testlauf muss bestanden sein.');
81
82 $staleRun = $runner->startRun('full', array($demo[0]['id']), 'single');
83 $stalePath = (string)$runner->runLogPath($staleRun['id']);
84 touch($stalePath, time() - 601);
85 clearstatcache(true, $stalePath);
86 $staleHistory = array_values(array_filter(
87 $runner->history(20),
88 static fn(array $item): bool => ($item['id'] ?? '') === $staleRun['id']
89 ));
90 selftest_assert(($staleHistory[0]['display_status'] ?? '') === 'interrupted', 'Verwaiste Weblaeufe muessen als unterbrochen erscheinen.');
91 selftest_assert(($runner->loadRun($staleRun['id'])['status'] ?? '') === 'running', 'Unterbrochene Laeufe muessen fortsetzbar bleiben.');
92} finally {
94}
95
96echo "PASS: dbxSelfTest entdeckt, isoliert, protokolliert und validiert Testlaeufe.\n";
Zentraler, auch ohne Web-Kernel nutzbarer Test-Orchestrator.
selftest_remove_tree(string $path)
selftest_assert(bool $condition, string $message)
if(!defined( 'IMG_WEBP')) define( 'IMG_WEBP'
exit
Definition index.php:146
foreach(array_slice($argv ?? array(), 1) as $argument) $runner
Definition run.php:15