From ecc
PHPUnit과 Pest, 팩토리, 데이터베이스 테스트, 페이크(fakes) 및 커버리지 목표를 사용한 라라벨 TDD(테스트 주도 개발) 가이드입니다.
npx claudepluginhub sam42-lab/everything-claude-code-krThis skill uses the workspace's default tool permissions.
PHPUnit과 Pest를 사용하여 80% 이상의 커버리지(단위 + 기능)를 목표로 하는 라라벨 애플리케이션용 테스트 주도 개발(TDD) 가이드입니다.
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
PHPUnit과 Pest를 사용하여 80% 이상의 커버리지(단위 + 기능)를 목표로 하는 라라벨 애플리케이션용 테스트 주도 개발(TDD) 가이드입니다.
범위에 따라 레이어를 선택하세요:
RefreshDatabase를 사용하세요. (테스트 실행 시 한 번 마이그레이션을 수행하고, 지원되는 경우 각 테스트를 트랜잭션으로 감쌉니다. 인메모리 DB의 경우 테스트마다 재마이그레이션될 수 있습니다.)DatabaseTransactions를 사용하세요.DatabaseMigrations를 사용하세요.데이터베이스를 사용하는 테스트의 기본값으로 RefreshDatabase를 사용하세요. 트랜잭션을 지원하는 DB의 경우 테스트 실행당 한 번 마이그레이션을 수행하고 각 테스트를 트랜잭션으로 래핑합니다. :memory: SQLite나 트랜잭션을 지원하지 않는 연결의 경우 매 테스트 전에 마이그레이션합니다.
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
final class ProjectControllerTest extends TestCase
{
use RefreshDatabase;
public function test_owner_can_create_project(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->postJson('/api/projects', [
'name' => 'New Project',
]);
$response->assertCreated();
$this->assertDatabaseHas('projects', ['name' => 'New Project']);
}
}
use App\Models\Project;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
final class ProjectIndexTest extends TestCase
{
use RefreshDatabase;
public function test_projects_index_returns_paginated_results(): void
{
$user = User::factory()->create();
Project::factory()->count(3)->for($user)->create();
$response = $this->actingAs($user)->getJson('/api/projects');
$response->assertOk();
$response->assertJsonStructure(['success', 'data', 'error', 'meta']);
}
}
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use function Pest\Laravel\actingAs;
use function Pest\Laravel\assertDatabaseHas;
uses(RefreshDatabase::class);
test('owner can create project', function () {
$user = User::factory()->create();
$response = actingAs($user)->postJson('/api/projects', [
'name' => 'New Project',
]);
$response->assertCreated();
assertDatabaseHas('projects', ['name' => 'New Project']);
});
use App\Models\Project;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use function Pest\Laravel\actingAs;
uses(RefreshDatabase::class);
test('projects index returns paginated results', function () {
$user = User::factory()->create();
Project::factory()->count(3)->for($user)->create();
$response = actingAs($user)->getJson('/api/projects');
$response->assertOk();
$response->assertJsonStructure(['success', 'data', 'error', 'meta']);
});
$user = User::factory()->state(['role' => 'admin'])->create();
RefreshDatabase를 사용하세요.assertDatabaseHas 사용을 권장합니다.use App\Models\Project;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
final class ProjectRepositoryTest extends TestCase
{
use RefreshDatabase;
public function test_project_can_be_retrieved_by_slug(): void
{
$project = Project::factory()->create(['slug' => 'alpha']);
$found = Project::query()->where('slug', 'alpha')->firstOrFail();
$this->assertSame($project->id, $found->id);
}
}
Bus::fake()Queue::fake()Mail::fake() 및 Notification::fake()Event::fake()use Illuminate\Support\Facades\Queue;
Queue::fake();
dispatch(new SendOrderConfirmation($order->id));
Queue::assertPushed(SendOrderConfirmation::class);
use Illuminate\Support\Facades\Notification;
Notification::fake();
$user->notify(new InvoiceReady($invoice));
Notification::assertSentTo($user, InvoiceReady::class);
use Laravel\Sanctum\Sanctum;
Sanctum::actingAs($user);
$response = $this->getJson('/api/projects');
$response->assertOk();
Http::fake()를 사용하세요.Http::assertSent()로 외부로 전송된 페이로드를 검증하세요.pcov 또는 XDEBUG_MODE=coverage를 사용하세요.php artisan testvendor/bin/phpunitvendor/bin/pestphpunit.xml에서 DB_CONNECTION=sqlite 및 DB_DATABASE=:memory:를 설정하세요.use Illuminate\Support\Facades\Gate;
$this->assertTrue(Gate::forUser($user)->allows('update', $project));
$this->assertFalse(Gate::forUser($otherUser)->allows('update', $project));
Inertia.js를 사용하는 경우, Inertia 테스트 헬퍼를 사용하여 컴포넌트 이름과 props를 검증하세요.
use App\Models\User;
use Inertia\Testing\AssertableInertia;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
final class DashboardInertiaTest extends TestCase
{
use RefreshDatabase;
public function test_dashboard_inertia_props(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->get('/dashboard');
$response->assertOk();
$response->assertInertia(fn (AssertableInertia $page) => $page
->component('Dashboard')
->where('user.id', $user->id)
->has('projects')
);
}
}
테스트를 Inertia 응답에 맞게 유지하려면 원시 JSON 어설션보다 assertInertia를 권장합니다.