2045c856e9
- Add 10 core testing guides (setup, AAA principles, PHPUnit/Pest, mocking, anti-patterns, PHP 8.4+, debugging, data factories, advanced edge cases) - Add 13 component testing guides covering all Laravel layers - Add standard templates for PHPUnit 10/11 and Pest v2/v3 including ArchitectureTest - Add Docker smart test runner, dependency installer, and CI/CD templates (GitHub Actions, GitLab CI) - Add 4 Claude Code skills (laravel-test-setup, laravel-unit-test with --all mode, laravel-test-review, laravel-mock-helper) - Add single unified installer script (sg-install-unit-testing.sh) with global support, CLI runners, and 1-click updater (sg-test-update) - Add comprehensive documentation (README.md, USAGE-GUIDE.md) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
100 lines
3.3 KiB
Markdown
100 lines
3.3 KiB
Markdown
# Component Guide: Artisan Console Commands
|
|
|
|
Artisan Commands xử lý các công việc chạy từ dòng lệnh (CLI), cron jobs, và lệnh bảo trì hệ thống.
|
|
|
|
---
|
|
|
|
## 1. Bản Chất Kiểm Thử Console Command
|
|
|
|
Khi test một Artisan Command, cần kiểm tra:
|
|
1. **Exit Code**: Trả về `Command::SUCCESS` (0) khi hoàn thành, hoặc `Command::FAILURE` (1) / `Command::INVALID` (2) khi có lỗi.
|
|
2. **Output trên màn hình**: Kiểm tra dòng thông báo in ra bằng `expectsOutput()`, `doesntExpectOutput()`, `expectsTable()`.
|
|
3. **User Interaction**: Kiểm tra câu hỏi tương tác như `expectsConfirmation()`, `expectsQuestion()`, `expectsChoice()`.
|
|
4. **Service Execution**: Đảm bảo Command gọi đúng Service xử lý logic ngầm bên dưới.
|
|
|
|
---
|
|
|
|
## 2. Mã Mẫu Chuẩn: Console Command Test
|
|
|
|
### Command Nguồn: `App\Console\Commands\PruneOldLogsCommand`
|
|
```php
|
|
namespace App\Console\Commands;
|
|
|
|
use Illuminate\Console\Command;
|
|
use App\Services\LogCleanupService;
|
|
|
|
class PruneOldLogsCommand extends Command
|
|
{
|
|
protected $signature = 'logs:prune {--days=30 : Số ngày lưu log cũ} {--force : Thực thi mà không hỏi lại}';
|
|
protected $description = 'Xóa các file log cũ hơn số ngày quy định';
|
|
|
|
public function handle(LogCleanupService $cleanupService): int
|
|
{
|
|
$days = (int) $this->option('days');
|
|
|
|
if ($days <= 0) {
|
|
$this->error('Số ngày phải lớn hơn 0.');
|
|
return self::INVALID;
|
|
}
|
|
|
|
if (!$this->option('force') && !$this->confirm("Bạn có chắc chắn muốn xóa log cũ hơn {$days} ngày?")) {
|
|
$this->info('Đã hủy thao tác.');
|
|
return self::SUCCESS;
|
|
}
|
|
|
|
$deletedCount = $cleanupService->deleteLogsOlderThan($days);
|
|
$this->info("Đã dọn dẹp thành công {$deletedCount} file log.");
|
|
|
|
return self::SUCCESS;
|
|
}
|
|
}
|
|
```
|
|
|
|
### Test Chuẩn: PHPUnit 10+
|
|
```php
|
|
namespace Tests\Unit\Console\Commands;
|
|
|
|
use Tests\TestCase;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
use Mockery;
|
|
use App\Services\LogCleanupService;
|
|
use Illuminate\Console\Command;
|
|
|
|
class PruneOldLogsCommandTest extends TestCase
|
|
{
|
|
#[Test]
|
|
public function it_fails_when_days_option_is_zero_or_negative(): void
|
|
{
|
|
$this->artisan('logs:prune --days=0')
|
|
->expectsOutput('Số ngày phải lớn hơn 0.')
|
|
->assertExitCode(Command::INVALID);
|
|
}
|
|
|
|
#[Test]
|
|
public function it_cancels_pruning_when_user_declines_confirmation(): void
|
|
{
|
|
$this->artisan('logs:prune --days=15')
|
|
->expectsConfirmation('Bạn có chắc chắn muốn xóa log cũ hơn 15 ngày?', 'no')
|
|
->expectsOutput('Đã hủy thao tác.')
|
|
->assertExitCode(Command::SUCCESS);
|
|
}
|
|
|
|
#[Test]
|
|
public function it_prunes_logs_successfully_when_forced(): void
|
|
{
|
|
// Mock service
|
|
$cleanupServiceMock = Mockery::mock(LogCleanupService::class);
|
|
$cleanupServiceMock->shouldReceive('deleteLogsOlderThan')
|
|
->once()
|
|
->with(30)
|
|
->andReturn(12);
|
|
|
|
$this->app->instance(LogCleanupService::class, $cleanupServiceMock);
|
|
|
|
$this->artisan('logs:prune --days=30 --force')
|
|
->expectsOutput('Đã dọn dẹp thành công 12 file log.')
|
|
->assertExitCode(Command::SUCCESS);
|
|
}
|
|
}
|
|
```
|