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; } }