mirror of
https://github.com/affaan-m/everything-claude-code.git
synced 2026-05-20 22:49:06 +08:00
Translate everything-claude-code repository to Japanese including: - 17 root documentation files - 60 agent documentation files - 80 command documentation files - 99 rule files across 18 language directories (common, angular, arkts, cpp, csharp, dart, fsharp, golang, java, kotlin, perl, php, python, ruby, rust, swift, typescript, web) - 199 skill documentation files Total: 455 files translated to Japanese with: - Consistent terminology glossary applied throughout - YAML field names preserved in English (name, description, etc.) - Code blocks and examples untouched (comments translated) - Markdown structure and relative links preserved - Professional translation maintaining technical accuracy This translation expands ECC accessibility to Japanese-speaking developers and teams. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
284 lines
8.5 KiB
Markdown
284 lines
8.5 KiB
Markdown
---
|
||
name: laravel-tdd
|
||
description: Laravel での TDD:PHPUnit と Pest、ファクトリー、データベーステスト、フェイク、カバレッジターゲット
|
||
origin: ECC
|
||
---
|
||
|
||
# Laravel TDD ワークフロー
|
||
|
||
PHPUnit と Pest を使用した Laravel アプリケーション用のテスト駆動開発。80%+ カバレッジ(ユニット + フィーチャー)。
|
||
|
||
## 使用時機
|
||
|
||
- Laravel の新機能またはエンドポイント
|
||
- バグ修正またはリファクタリング
|
||
- Eloquent モデル、ポリシー、ジョブ、通知のテスト
|
||
- プロジェクトが PHPUnit を標準化していない限り、新しいテストには Pest を優先
|
||
|
||
## 仕組み
|
||
|
||
### RED-GREEN-REFACTOR サイクル
|
||
|
||
1) テスト失敗を書く
|
||
2) 最小限の変更を実装して合格させる
|
||
3) テストを緑に保ちながらリファクタリング
|
||
|
||
### テスト層
|
||
|
||
- **ユニット**:純粋な PHP クラス、値オブジェクト、サービス
|
||
- **フィーチャー**:HTTP エンドポイント、認証、バリデーション、ポリシー
|
||
- **統合**:データベース + キュー + 外部バウンダリー
|
||
|
||
スコープに基づいて層を選択:
|
||
|
||
- **ユニット**テストを純粋なビジネスロジックとサービスに使用。
|
||
- **フィーチャー**テストを HTTP、認証、バリデーション、レスポンス形状に使用。
|
||
- **統合**テストを DB/キュー/外部サービスを一緒に検証するときに使用。
|
||
|
||
### データベース戦略
|
||
|
||
- `RefreshDatabase` ほとんどのフィーチャー/統合テスト用(テスト実行ごとにマイグレーションを 1 回実行し、次に各テストをトランザクション内でラップ;メモリ内データベースは各テストごとに再マイグレーションする可能性がある)
|
||
- `DatabaseTransactions` スキーマがすでにマイグレーションされており、テストごとのロールバックのみが必要なとき
|
||
- `DatabaseMigrations` すべてのテストで完全な migrate/fresh が必要なとき、またはコストを負担できるとき
|
||
|
||
`RefreshDatabase` をデータベースに触れるテストのデフォルトとして使用:トランザクション サポート付きデータベースの場合、マイグレーション ステップ フラグを使用して テスト実行ごとに 1 回実行し、次に各テストをトランザクション内でラップします;`:memory:` SQLite または非トランザクションの接続では、各テストの前にマイグレーションします。スキーマがすでにマイグレーションされており、テストごとのロールバックのみが必要なときは `DatabaseTransactions` を使用します。
|
||
|
||
### テストフレームワーク選択
|
||
|
||
- **新しいテストの場合は Pest をデフォルト**で使用。
|
||
- **PHPUnit** はプロジェクトがすでにそれを標準化している、またはPHPUnit 固有のツールが必要なときのみ使用。
|
||
|
||
## 例
|
||
|
||
### PHPUnit 例
|
||
|
||
```php
|
||
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']);
|
||
}
|
||
}
|
||
```
|
||
|
||
### フィーチャーテスト例(HTTP レイヤー)
|
||
|
||
```php
|
||
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']);
|
||
}
|
||
}
|
||
```
|
||
|
||
### Pest 例
|
||
|
||
```php
|
||
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']);
|
||
});
|
||
```
|
||
|
||
### フィーチャーテスト Pest 例(HTTP レイヤー)
|
||
|
||
```php
|
||
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']);
|
||
});
|
||
```
|
||
|
||
### ファクトリーと状態
|
||
|
||
- テストデータにはファクトリーを使用
|
||
- エッジケース(アーカイブ済み、管理者、トライアル)の状態を定義
|
||
|
||
```php
|
||
$user = User::factory()->state(['role' => 'admin'])->create();
|
||
```
|
||
|
||
### データベーステスト
|
||
|
||
- クリーンな状態には `RefreshDatabase` を使用
|
||
- テストを隔離して決定論的に保つ
|
||
- 手動クエリより `assertDatabaseHas` を優先
|
||
|
||
### 永続性テスト例
|
||
|
||
```php
|
||
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()` ドメインイベント用
|
||
|
||
```php
|
||
use Illuminate\Support\Facades\Queue;
|
||
|
||
Queue::fake();
|
||
|
||
dispatch(new SendOrderConfirmation($order->id));
|
||
|
||
Queue::assertPushed(SendOrderConfirmation::class);
|
||
```
|
||
|
||
```php
|
||
use Illuminate\Support\Facades\Notification;
|
||
|
||
Notification::fake();
|
||
|
||
$user->notify(new InvoiceReady($invoice));
|
||
|
||
Notification::assertSentTo($user, InvoiceReady::class);
|
||
```
|
||
|
||
### 認証テスト(Sanctum)
|
||
|
||
```php
|
||
use Laravel\Sanctum\Sanctum;
|
||
|
||
Sanctum::actingAs($user);
|
||
|
||
$response = $this->getJson('/api/projects');
|
||
$response->assertOk();
|
||
```
|
||
|
||
### HTTP と外部サービス
|
||
|
||
- `Http::fake()` を使用して外部 API を隔離
|
||
- `Http::assertSent()` で送信ペイロードをアサート
|
||
|
||
### カバレッジターゲット
|
||
|
||
- ユニット + フィーチャーテストで 80%+ カバレッジを実施
|
||
- CI では `pcov` または `XDEBUG_MODE=coverage` を使用
|
||
|
||
### テストコマンド
|
||
|
||
- `php artisan test`
|
||
- `vendor/bin/phpunit`
|
||
- `vendor/bin/pest`
|
||
|
||
### テスト設定
|
||
|
||
- `phpunit.xml` を使用して `DB_CONNECTION=sqlite` と `DB_DATABASE=:memory:` を設定して高速テスト
|
||
- テストは dev/prod データに触れないように別の env を保つ
|
||
|
||
### 認可テスト
|
||
|
||
```php
|
||
use Illuminate\Support\Facades\Gate;
|
||
|
||
$this->assertTrue(Gate::forUser($user)->allows('update', $project));
|
||
$this->assertFalse(Gate::forUser($otherUser)->allows('update', $project));
|
||
```
|
||
|
||
### Inertia フィーチャーテスト
|
||
|
||
Inertia.js 使用時、Inertia テスティングヘルパーでコンポーネント名とプロップをアサート。
|
||
|
||
```php
|
||
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')
|
||
);
|
||
}
|
||
}
|
||
```
|
||
|
||
生の JSON アサーションより `assertInertia` を優先して、テストを Inertia レスポンスに合わせておく。
|