Files
agent-unit-testing/docs/components/11-artisan-commands.md
T
Pham-Tan-Thien 2045c856e9 feat: complete Smartgift AI Laravel unit testing toolkit
- 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>
2026-09-07 16:41:37 +07:00

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