controller-testing について
controller-testingは、Laravelのコントローラーに対するHTTP機能テスト用スキルです。ルート、認可、バリデーション、永続化の挙動に基づくテスト設計を支援し、WebとJSON APIの例を扱います。
主な機能
- 01コントローラーアクションのテスト手順
- 02WebとJSON APIのテストパターン
- 03ネストしたルートとバインディングの確認
- 04認可とバリデーションのアサーション
- 05アクション別の参考テンプレート
活用シーン
- 01LaravelコントローラーのHTTPアクションをテスト
- 02ネストしたルートのバインディングと権限を確認
- 03バリデーションと永続化の結果を検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ hosmelq/ skills --skill controller-testingインストール後、Claude Code で/controller-testingを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/route-patterns.mdreferences/actions/create.mddestroy.mdedit.mdindex.mdshow.mdstore.mdupdate.mdreferences/modes/api-json.mdreferences/validation/api-login-validation.mdprepare-for-validation.mdrequired-with-and-array.mdscoped-exists-and-unique.mdstore-validates-fields.mdupdate-validates-fields.md詳細
コントローラーテスト
適用する場合
このスキルは、タスクがLaravel のコントローラーフィーチャーテスト(コントローラーのアクションレベルの HTTP 動作)に関する場合にのみ有効にしてください。以下のような手がかりが含まれる場合が対象です。
- テストファイルのパスが
tests/Feature/Http/Controllers/**(tests/Feature/Http/Controllers/Api/**を含む)配下にある場合。これが主な判断基準です。 - タスクがコントローラーアクションを明示的に対象とし、アクションレベルの
describe('create' | 'destroy' | 'edit' | 'index' | 'show' | 'store' | 'update')を使用している場合。 route(...)、ネストされたパラメーター、ルートモデルバインディングのスコープ確認を使ったコントローラールートのアサーション。- 認証/認可の結果とコントローラーのトランスポートに関するアサーション:
- Web/セッション(
get、post、patch、delete、assertInertia、リダイレクト)、または - API/JSON(
getJson、postJson、patchJson、deleteJson、JSON アサーション)。
- Web/セッション(
describe('store') だけを根拠にこのスキルを有効にしないでください(Fortify/認証フローなど、多くのコントローラー以外のフィーチャーテストでも同じ動詞が使われます)。
モデル/ユニットテスト、サービス層のテスト、コンソールコマンド、または HTTP 以外の動作には、このスキルを使用しないでください。
キルスイッチ/優先順位
コントローラーに焦点を当てたフィーチャーテストでは、このスキルは pest-testing より優先されます。
コントローラーテストの作業で pest-testing が選択された場合は、作業を中断し、直ちに controller-testing に切り替えてください。
クイックスタート
# Create file only when needed
php artisan make:test --pest Http/Controllers/<Name>ControllerTest --no-interaction
# Run only the affected file
php artisan test --compact tests/Feature/Http/Controllers/<Name>ControllerTest.php
# Optional focused rerun
php artisan test --compact --filter="<test name>"
判断ワークフロー
- コントローラーアクション、フォームリクエスト、ポリシー、リソース、ルート定義を調べ、テスト対象の契約を導き出します。
- トランスポートモードを選択します:Web/セッション、または API/JSON。
- ルートの形式(フラットかネストか)とパラメーターキーを特定します。
- テスト対象の各アクションに対し、該当する場合は以下のベースラインを順番に適用します:
- 認証が必要
- ポリシーによる拒否(
403) - バインディングの不一致(
404) - バリデーション用データセット(
store/update) - 成功レスポンスと永続化のアサーション
- アクション/ルールのパターンに必要なリファレンスファイルのみを読み込みます。
出力時のガードレール(コントローラーテストをすっきり保つ)
これらのガードレールは、テストが冗長で一貫性を欠くのを防ぐためのものです。
- コントローラーの契約を信頼できる情報源として扱います。テンプレートは出発点にすぎません。コントローラーに実装された実際のリクエストペイロード、レスポンス形式、リダイレクト、リソース、ポリシーのフローに合わせて調整してください。
403テストは最小限にします。アクセス禁止のケースでは、通常、完全なペイロードを送信する必要はありません(認可はバリデーションより先に失敗するはずです)。- バリデーション用データセットは、小さく安定したものにします:
- 各データセットの
dataには、そのルールを発生させるために必要なフィールドのみを含めます。すべてのケースで完全な「有効なペイロード」を繰り返さないでください。 - 失敗するフィールドすべてについて、バリデーションメッセージをアサートします。これらのデータセットでは、キーのみの期待値を使用しないでください。
- 複数のフィールドで
sometimes|required形式の空値ルールが共有されている場合は、これらすべてのフィールドに空文字列を送信し、それぞれの必須メッセージをアサートするデータセットケースを1つ使うことを優先します。このパターンを代表的なフィールド1つだけに減らさないでください。 post(...)/patch(...)を直接使うことを優先し、それ以外では確実なリダイレクト元のアサーションができない場合を除き、from(...)は避けてください。
- 各データセットの
- ルートベースのリダイレクトを優先します。名前付きルートがある場合は
assertRedirectToRoute(...)を使い、遷移先が名前付きルートではない場合、または設定によって決まる場合に限りassertRedirect(...)を使ってください。
基本となる 403 対 404 のルール
以下を信頼できる情報源として使用してください。
- ルートバインディングが正しく解決され、認可によってアクセスが拒否される場合は、
assertForbidden()(403)をアサートします。 - ルートモデルバインディングが失敗する場合(親子チェーンの誤り、スコープ付きバインディングの不一致)は、
assertNotFound()(404)をアサートします。
結果を安定させるためのアクターコンテキスト:
403テスト:バインディングを解決できるものの、権限を持たないスコープ内のアクターを認証します。- バリデーションテストと成功パステスト:認可されたスコープ内のアクターを認証します。
404のバインディング不一致テスト:バインディングが最初に失敗するため、認証済みであればどのアクターでもかまいません。
基本の参照先
必要なものだけを読み込んでください。
- API/JSON の適用ガイドと完全な例:
references/modes/api-json.md
- ネストされたルートの命名とパラメーターの組み合わせ:
references/route-patterns.md
- アクションごとのテンプレート(Web/セッション優先):
references/actions/create.mdreferences/actions/destroy.mdreferences/actions/edit.mdreferences/actions/index.mdreferences/actions/show.mdreferences/actions/store.mdreferences/actions/update.md
- バリデーションの一覧(必要なルールだけを組み合わせてください):
references/validation/store-validates-fields.mdreferences/validation/update-validates-fields.md
- 対象を絞ったバリデーションパターン(一致するルールがある場合は、まずこちらを参照してください):
references/validation/required-with-and-array.mdreferences/validation/scoped-exists-and-unique.mdreferences/validation/prepare-for-validation.mdreferences/validation/api-login-validation.md
アクションの参照先は、Web/セッション優先のテンプレートです。API/JSON コントローラーでは、テスト対象のコントローラー/リソースの契約に基づき、references/modes/api-json.md を使ってアサーションを適用しつつ、同じアクション構造を維持してください。
トランスポートごとの基本アサーション
Web/セッションモード:
requires authentication-> ログインルートへリダイレクトします。- バリデーションエラー ->
assertRedirectBackWithErrors(...)。 - ページアクション ->
assertOk()+assertInertia(...)。 - 更新アクション -> リダイレクト + 永続化アサーション。
- トースト/フラッシュのアサーションは任意で、アプリ固有です。
API/JSON モード:
- 保護されたエンドポイント:
requires authentication->assertUnauthorized()。 - 公開エンドポイント:保護されていないエンドポイントでは、認証必須のテストを省略します。
- バリデーションエラー ->
assertUnprocessable()+assertJsonValidationErrors(...)。 - 成功アクション ->
assertOk()/assertCreated()/assertNoContent()+ JSON + 永続化アサーション。 - キーだけでなくバリデーションメッセージもアサートし、API の正確な契約をテストで検証してください。
注意事項
- 1 階層、2 階層、3 階層の例はパターンであり、上限ではありません。
destroyでは、モデルの動作に応じて永続化アサーションを選んでください。- ソフト削除モデルには
assertSoftDeleted(...)を使用します。 - それ以外の場合は
assertModelMissing(...)を使用します。
- ソフト削除モデルには
- アサーションでは、アプリで使われている識別子の形式(
id、public_id、スラッグ、ルートキー)を使用してください。