Add 100+ automated unit tests from .expect file specifications Add session system test Add rsx:constants:regenerate command test Add rsx:logrotate command test Add rsx:clean command test Add rsx:manifest:stats command test Add model enum system test Add model mass assignment prevention test Add rsx:check command test Add migrate:status command test 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
163 lines
4.8 KiB
PHP
163 lines
4.8 KiB
PHP
<?php
|
|
/**
|
|
* CODING CONVENTION:
|
|
* This file follows the coding convention where variable_names and function_names
|
|
* use snake_case (underscore_wherever_possible).
|
|
*/
|
|
|
|
namespace App\RSpade\Commands\Rsx;
|
|
|
|
use App\Console\Commands\FrameworkDeveloperCommand;
|
|
use App\RSpade\Core\Manifest\Manifest;
|
|
use Exception;
|
|
use ReflectionClass;
|
|
|
|
class Rsx_Test_Command extends FrameworkDeveloperCommand
|
|
{
|
|
/**
|
|
* The name and signature of the console command.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $signature = 'rsx:test
|
|
{test? : Specific test class to run}
|
|
{--filter= : Run only tests matching this pattern}';
|
|
|
|
/**
|
|
* The console command description.
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $description = 'Run RSX framework tests';
|
|
|
|
/**
|
|
* Execute the console command.
|
|
*
|
|
* @return int
|
|
*/
|
|
public function handle()
|
|
{
|
|
$specific_test = $this->argument('test');
|
|
$filter = $this->option('filter');
|
|
|
|
$this->info('RSX Test Runner');
|
|
$this->info('================');
|
|
$this->newLine();
|
|
|
|
// Rebuild manifest to ensure we have latest test classes
|
|
$this->line('Building manifest...');
|
|
Manifest::init();
|
|
|
|
// Get all test classes extending Rsx_Test_Abstract
|
|
$test_classes = Manifest::php_get_extending('Rsx_Test_Abstract');
|
|
|
|
if (empty($test_classes)) {
|
|
$this->warn('No test classes found.');
|
|
$this->line('Test classes should extend App\\RSpade\\Core\\Testing\\Rsx_Test_Abstract');
|
|
|
|
return 0;
|
|
}
|
|
|
|
$total_tests = 0;
|
|
$total_passed = 0;
|
|
$total_failed = 0;
|
|
$total_skipped = 0;
|
|
|
|
foreach ($test_classes as $test_class_info) {
|
|
if (!isset($test_class_info['fqcn'])) {
|
|
continue;
|
|
}
|
|
|
|
$class_name = $test_class_info['fqcn'];
|
|
|
|
// Skip if specific test requested and this isn't it
|
|
if ($specific_test && !str_contains($class_name, $specific_test)) {
|
|
continue;
|
|
}
|
|
|
|
// Skip abstract classes
|
|
$reflection = new ReflectionClass($class_name);
|
|
// @PHP-REFLECT-01-EXCEPTION - Test runner needs ReflectionClass for filtering
|
|
if ($reflection->isAbstract()) {
|
|
continue;
|
|
}
|
|
|
|
$short_name = basename(str_replace('\\', '/', $class_name));
|
|
$this->info("Running: {$short_name}");
|
|
|
|
try {
|
|
// Run the tests
|
|
$results = $class_name::run();
|
|
|
|
// Process results
|
|
foreach ($results as $test_name => $result) {
|
|
// Apply filter if provided
|
|
if ($filter && !str_contains($test_name, $filter)) {
|
|
continue;
|
|
}
|
|
|
|
$total_tests++;
|
|
|
|
switch ($result['status']) {
|
|
case 'passed':
|
|
$total_passed++;
|
|
$this->line(" ✓ {$test_name}");
|
|
break;
|
|
|
|
case 'failed':
|
|
$total_failed++;
|
|
$this->error(" ✗ {$test_name}");
|
|
$this->line(" {$result['message']}", 'fg=red');
|
|
if (isset($result['file']) && isset($result['line'])) {
|
|
$this->line(" at {$result['file']}:{$result['line']}", 'fg=gray');
|
|
}
|
|
break;
|
|
|
|
case 'skipped':
|
|
$total_skipped++;
|
|
$this->line(" - {$test_name} (skipped)", 'fg=yellow');
|
|
$this->line(" {$result['message']}", 'fg=gray');
|
|
break;
|
|
}
|
|
}
|
|
} catch (Exception $e) {
|
|
$this->error(' Error running test class: ' . $e->getMessage());
|
|
$total_failed++;
|
|
}
|
|
|
|
$this->newLine();
|
|
}
|
|
|
|
// Summary
|
|
$this->info('Test Summary');
|
|
$this->info('============');
|
|
$this->line("Total: {$total_tests}");
|
|
|
|
if ($total_passed > 0) {
|
|
$this->line("Passed: {$total_passed}", 'fg=green');
|
|
}
|
|
if ($total_failed > 0) {
|
|
$this->line("Failed: {$total_failed}", 'fg=red');
|
|
}
|
|
if ($total_skipped > 0) {
|
|
$this->line("Skipped: {$total_skipped}", 'fg=yellow');
|
|
}
|
|
|
|
$this->newLine();
|
|
|
|
if ($total_failed > 0) {
|
|
$this->error('Tests failed!');
|
|
|
|
return 1;
|
|
}
|
|
if ($total_tests === 0) {
|
|
$this->warn('No tests were run.');
|
|
|
|
return 0;
|
|
}
|
|
$this->info('All tests passed!');
|
|
|
|
return 0;
|
|
}
|
|
}
|