folderweb/devel/tests/run.php
Ruben 449e6f8e03 Update framework testing infrastructure and standards
- Add phpt test runner and suite for app functions
- Introduce testing workflow to AGENT.md
- Add tests for cache, content, context, helpers, hooks, plugins,
  rendering
- Mount tests directory in dev container
2026-03-17 12:51:07 +01:00

112 lines
2.9 KiB
PHP

<?php
// phpt test runner — execute via run.sh, runs inside the container
const GREEN = "\033[32m";
const RED = "\033[31m";
const YELLOW = "\033[33m";
const RESET = "\033[0m";
const BOLD = "\033[1m";
$filter = $argv[1] ?? null;
$iterator = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator(__DIR__, FilesystemIterator::SKIP_DOTS)
);
$files = [];
foreach ($iterator as $file) {
if ($file->getExtension() === 'phpt') {
$files[] = $file->getPathname();
}
}
sort($files);
$pass = 0;
$fail = 0;
$skip = 0;
foreach ($files as $file) {
$rel = ltrim(substr($file, strlen(__DIR__), -5), '/');
if ($filter !== null && !str_contains($rel, $filter)) {
continue;
}
$sections = parse_phpt(file_get_contents($file));
$title = trim($sections['TEST'] ?? $rel);
if (!isset($sections['FILE']) || !isset($sections['EXPECT'])) {
echo RED . 'INVALID' . RESET . " $name (missing --FILE-- or --EXPECT--)\n";
$fail++;
continue;
}
if (isset($sections['SKIPIF'])) {
$result = trim(run_php($sections['SKIPIF']));
if (str_starts_with($result, 'skip')) {
$reason = ltrim(substr($result, 4));
echo YELLOW . 'SKIP' . RESET . " $title" . ($reason ? "$reason" : '') . "\n";
$skip++;
continue;
}
}
$actual = trim(run_php($sections['FILE']));
$expected = trim($sections['EXPECT']);
if ($actual === $expected) {
echo GREEN . 'PASS' . RESET . " $title\n";
$pass++;
} else {
echo RED . 'FAIL' . RESET . " $title\n";
show_diff($expected, $actual);
$fail++;
}
}
$total = $pass + $fail + $skip;
echo "\n" . BOLD . "Results: $pass/$total passed" . ($skip ? ", $skip skipped" : '') . RESET . "\n";
exit($fail > 0 ? 1 : 0);
// ---- helpers ----
function parse_phpt(string $content): array
{
$sections = [];
$current = null;
foreach (explode("\n", $content) as $line) {
if (preg_match('/^--([A-Z]+)--$/', rtrim($line), $m)) {
$current = $m[1];
$sections[$current] = '';
} elseif ($current !== null) {
$sections[$current] .= $line . "\n";
}
}
return $sections;
}
function run_php(string $code): string
{
$tmp = tempnam('/tmp', 'phpt_');
file_put_contents($tmp, $code);
$output = shell_exec("php $tmp 2>&1");
unlink($tmp);
return $output ?? '';
}
function show_diff(string $expected, string $actual): void
{
$exp = explode("\n", $expected);
$act = explode("\n", $actual);
$max = max(count($exp), count($act));
for ($i = 0; $i < $max; $i++) {
$e = $exp[$i] ?? null;
$a = $act[$i] ?? null;
if ($e === $a) {
echo " $e\n";
} else {
if ($e !== null) echo RED . " - $e" . RESET . "\n";
if ($a !== null) echo GREEN . " + $a" . RESET . "\n";
}
}
}