#!/usr/bin/env php setName('test') ->setDescription('运行测试套件') ->addArgument('type', '测试类型: unit, integration, api, e2e, performance, security') ->addOption('filter', 'f', '过滤测试用例') ->addOption('coverage', 'c', '生成覆盖率报告') ->addOption('parallel', 'p', '并行测试', false, 4); } protected function execute(\Fendx\Cli\Input\InputInterface $input, \Fendx\Cli\Output\OutputInterface $output): int { $type = $input->getArgument('type') ?? 'all'; $filter = $input->getOption('filter'); $coverage = $input->getOption('coverage'); $parallel = $input->getOption('parallel'); $output->writeln("运行 {$type} 测试..."); return match ($type) { 'unit' => $this->runUnitTests($output, $filter, $coverage), 'integration' => $this->runIntegrationTests($output, $filter), 'api' => $this->runApiTests($output, $filter), 'e2e' => $this->runE2ETests($output, $filter), 'performance' => $this->runPerformanceTests($output), 'security' => $this->runSecurityTests($output), 'all' => $this->runAllTests($output, $filter, $coverage, $parallel), default => $this->showError($output, "未知的测试类型: {$type}") }; } private function runUnitTests($output, $filter, $coverage): int { $output->writeln("运行单元测试..."); $command = "vendor/bin/phpunit tests/Unit --colors=always"; if ($filter) { $command .= " --filter {$filter}"; } if ($coverage) { $command .= " --coverage-html reports/coverage --coverage-clover reports/coverage.xml"; } $this->executeCommand($output, $command); if ($coverage) { $output->writeln("覆盖率报告已生成: reports/coverage/index.html"); } return 0; } private function runIntegrationTests($output, $filter): int { $output->writeln("运行集成测试..."); // 启动测试环境 $this->executeCommand($output, "docker-compose -f docker-compose.test.yml up -d"); sleep(10); // 等待服务启动 $command = "vendor/bin/phpunit tests/Integration --colors=always"; if ($filter) { $command .= " --filter {$filter}"; } $result = $this->executeCommand($output, $command); // 清理测试环境 $this->executeCommand($output, "docker-compose -f docker-compose.test.yml down"); return $result; } private function runApiTests($output, $filter): int { $output->writeln("运行 API 测试..."); $command = "vendor/bin/codecept run api --colors"; if ($filter) { $command .= " -g {$filter}"; } return $this->executeCommand($output, $command); } private function runE2ETests($output, $filter): int { $output->writeln("运行端到端测试..."); // 启动完整环境 $this->executeCommand($output, "docker-compose up -d"); $this->executeCommand($output, "kubectl apply -f k8s/"); sleep(30); // 等待所有服务就绪 $command = "vendor/bin/codecept run e2e --colors"; if ($filter) { $command .= " -g {$filter}"; } $result = $this->executeCommand($output, $command); // 清理环境 $this->executeCommand($output, "kubectl delete -f k8s/"); $this->executeCommand($output, "docker-compose down"); return $result; } private function runPerformanceTests($output): int { $output->writeln("运行性能测试..."); // 并发测试 $this->executeCommand($output, "ab -n 10000 -c 100 http://localhost/api/users"); // 内存测试 $this->executeCommand($output, "php bin/console benchmark:memory"); // 数据库性能测试 $this->executeCommand($output, "php bin/console benchmark:database"); return 0; } private function runSecurityTests($output): int { $output->writeln("运行安全测试..."); // 依赖漏洞扫描 $this->executeCommand($output, "composer audit"); // 代码安全扫描 $this->executeCommand($output, "vendor/bin/phpstan analyse --level=8"); // API 安全测试 $this->executeCommand($output, "vendor/bin/codecept run security"); return 0; } private function runAllTests($output, $filter, $coverage, $parallel): int { $output->writeln("运行所有测试..."); $tests = [ 'unit' => $this->runUnitTests($output, $filter, $coverage), 'integration' => $this->runIntegrationTests($output, $filter), 'api' => $this->runApiTests($output, $filter), ]; $failed = array_filter($tests, fn($result) => $result !== 0); if (empty($failed)) { $output->writeln("所有测试通过! ✅"); return 0; } else { $output->writeln("部分测试失败! ❌"); return 1; } } private function executeCommand($output, string $command): int { $output->writeln("执行: {$command}"); $process = proc_open($command, [ 1 => ['pipe', 'w'], 2 => ['pipe', 'w'], ], $pipes); if (!is_resource($process)) { return 1; } // 读取输出 while (($line = fgets($pipes[1])) !== false) { $output->write($line); } // 读取错误输出 while (($line = fgets($pipes[2])) !== false) { $output->write("{$line}"); } return proc_close($process); } private function showError($output, string $message): int { $output->writeln("{$message}"); return 1; } } /** * 部署命令 */ class DeployCommand extends \Fendx\Cli\Command\Command { protected function configure(): void { $this->setName('deploy') ->setDescription('部署应用到指定环境') ->addArgument('environment', '部署环境: local, docker, k8s') ->addOption('force', 'f', '强制部署', false); } protected function execute(\Fendx\Cli\Input\InputInterface $input, \Fendx\Cli\Output\OutputInterface $output): int { $environment = $input->getArgument('environment'); $force = $input->getOption('force'); $output->writeln("部署到 {$environment} 环境..."); return match ($environment) { 'local' => $this->deployLocal($output, $force), 'docker' => $this->deployDocker($output, $force), 'k8s' => $this->deployKubernetes($output, $force), default => $this->showError($output, "未知的环境: {$environment}") }; } private function deployLocal($output, $force): int { $output->writeln("部署到本地环境..."); // 检查依赖 $this->executeCommand($output, "composer install"); // 运行迁移 $this->executeCommand($output, "php bin/console migrate:run"); // 设置权限 $this->executeCommand($output, "chmod -R 755 storage/ runtime/"); $output->writeln("本地部署完成! 🎉"); return 0; } private function deployDocker($output, $force): int { $output->writeln("部署到 Docker 环境..."); if ($force) { $this->executeCommand($output, "docker-compose down --volumes"); } $this->executeCommand($output, "docker-compose up -d --build"); // 等待服务启动 $output->writeln("等待服务启动..."); sleep(30); // 健康检查 $this->executeCommand($output, "curl -f http://localhost/health"); $output->writeln("Docker 部署完成! 🐳"); return 0; } private function deployKubernetes($output, $force): int { $output->writeln("部署到 Kubernetes 环境..."); if ($force) { $this->executeCommand($output, "kubectl delete namespace fendx"); } $this->executeCommand($output, "kubectl apply -f k8s/"); // 等待部署完成 $this->executeCommand($output, "kubectl rollout status deployment/fendx-php -n fendx"); $output->writeln("Kubernetes 部署完成! ☸️"); return 0; } } /** * 基准测试命令 */ class BenchmarkCommand extends \Fendx\Cli\Command\Command { protected function configure(): void { $this->setName('benchmark') ->setDescription('运行性能基准测试') ->addArgument('type', '测试类型: all, memory, database, cache, api'); } protected function execute(\Fendx\Cli\Input\InputInterface $input, \Fendx\Cli\Output\OutputInterface $output): int { $type = $input->getArgument('type') ?? 'all'; $output->writeln("运行 {$type} 基准测试..."); return match ($type) { 'memory' => $this->benchmarkMemory($output), 'database' => $this->benchmarkDatabase($output), 'cache' => $this->benchmarkCache($output), 'api' => $this->benchmarkApi($output), 'all' => $this->benchmarkAll($output), default => $this->showError($output, "未知的测试类型: {$type}") }; } private function benchmarkMemory($output): int { $output->writeln("内存基准测试..."); $start = memory_get_usage(); // 模拟业务逻辑 for ($i = 0; $i < 100000; $i++) { $data = ['id' => $i, 'name' => "user_{$i}", 'email' => "user{$i}@example.com"]; $json = json_encode($data); $array = json_decode($json, true); } $end = memory_get_usage(); $used = ($end - $start) / 1024 / 1024; $output->writeln("内存使用: {$used} MB"); return 0; } private function benchmarkDatabase($output): int { $output->writeln("数据库基准测试..."); $start = microtime(true); // 模拟数据库查询 for ($i = 0; $i < 1000; $i++) { // 这里应该执行实际的数据库查询 usleep(100); // 模拟 0.1ms 查询时间 } $end = microtime(true); $duration = ($end - $start) * 1000; $output->writeln("1000 次查询耗时: {$duration} ms"); return 0; } private function benchmarkCache($output): int { $output->writeln("缓存基准测试..."); $start = microtime(true); // 模拟缓存操作 for ($i = 0; $i < 10000; $i++) { // 模拟缓存写入 usleep(10); // 模拟 0.01ms 缓存时间 // 模拟缓存读取 usleep(5); // 模拟 0.005ms 缓存时间 } $end = microtime(true); $duration = ($end - $start) * 1000; $output->writeln("20000 次缓存操作耗时: {$duration} ms"); return 0; } private function benchmarkApi($output): int { $output->writeln("API 基准测试..."); $this->executeCommand($output, "ab -n 1000 -c 10 http://localhost/api/users"); return 0; } private function benchmarkAll($output): int { $this->benchmarkMemory($output); $this->benchmarkDatabase($output); $this->benchmarkCache($output); $this->benchmarkApi($output); return 0; } } // 运行控制台应用 try { $app = new ConsoleApplication(); $app->run(); } catch (\Exception $e) { echo "Error: " . $e->getMessage() . "\n"; exit(1); }