はじめに
Laravelは、HTTPリクエストをシミュレートしてレスポンスを検証するための、豊富なAPIを提供しています。 実際のHTTPサーバーを立てることなく、アプリケーションへのリクエストをテスト内で再現できます。get() メソッドはアプリケーションに GET リクエストを送り、assertStatus() は返ってきたレスポンスのHTTPステータスコードを検証します。
テスト実行中はCSRFミドルウェアが自動的に無効になります。テストで明示的に無効化する必要はありません。
リクエストの作成
テスト内ではget、post、put、patch、delete メソッドを使ってリクエストを送れます。
これらのメソッドはネットワークリクエストを実際には発行せず、アプリケーション内部でシミュレートします。
返り値は Illuminate\Testing\TestResponse のインスタンスで、様々なアサーションメソッドを提供します。
リクエストヘッダーのカスタマイズ
withHeaders() メソッドを使ってリクエストのヘッダーをカスタマイズできます。
クッキー
withCookie() または withCookies() メソッドでリクエスト前にクッキー値を設定できます。
セッションと認証
withSession() メソッドを使ってリクエスト前にセッションデータを設定できます。
actingAs() メソッドで認証ユーザーとしてリクエストを送れます。モデルファクトリーと組み合わせて使います。
actingAs() の第2引数にガード名を渡すと、そのガードで認証されます。テストの間はそのガードがデフォルトになります。
actingAsGuest() を使います。
レスポンスのデバッグ
テスト中にレスポンスの内容を確認したい場合はdump、dumpHeaders、dumpSession メソッドを使います。
dd、ddHeaders、ddBody、ddJson、ddSession メソッドを使います。
例外のテスト
特定の例外がスローされることをテストするには、Exceptions ファサードを使います。
assertNotReported や assertNothingReported を使います。
withoutExceptionHandling() を使います。
assertThrows() を使います。
assertDoesntThrow() を使います。
JSON APIのテスト
LaravelはJSON APIのテストのためのヘルパーを多数提供しています。json、getJson、postJson、putJson、patchJson、deleteJson、optionsJson メソッドを使ってJSONリクエストを送れます。
assertJson() はレスポンスを配列に変換し、指定した配列がJSONレスポンスの中に含まれているかを検証します。JSONに他のプロパティが存在していても、指定したフラグメントが含まれていればテストは通過します。完全一致のアサーション
assertExactJson() を使うと、返却されたJSONと指定した配列が完全に一致することを検証できます。
JSONパスのアサーション
assertJsonPath() を使って、指定したパスにあるデータを検証できます。
フルーエントなJSONテスト
assertJson() にクロージャを渡すと、AssertableJson インスタンスを使ってフルーエントにアサーションを記述できます。
has() と missing() を使います。
hasAll() や missingAll() を使います。
JSONコレクションのアサーション
ルートが複数のアイテムを含むJSONレスポンスを返す場合、has() メソッドでアイテム数やコレクションの中身を検証できます。
each() を使います。
JSONの型アサーション
whereType() や whereAllType() を使ってプロパティの型を検証できます。
| 文字で複数の型を指定することもできます。いずれかの型に一致すればアサーションは通過します。
string、integer、double、boolean、array、null です。
認証テスト
actingAs() を使って認証されたユーザーとしてリクエストを送れます。
ユーザー登録フローのテスト例
実際のユーザー登録エンドポイントをテストする例です。セッションのテスト
withSession() でセッションデータを事前にセットしてリクエストを送れます。
assertSessionHas() でセッションに値が存在するかを検証できます。
セッションアサーションの一覧
| メソッド | 説明 |
|---|---|
assertSessionHas($key, $value) | セッションに指定したキーと値が存在する |
assertSessionHasAll([...]) | セッションに複数のキーと値が存在する |
assertSessionHasErrors($keys) | セッションにバリデーションエラーが存在する |
assertSessionHasErrorsIn($bag, $keys) | 指定したエラーバッグにエラーが存在する |
assertSessionHasNoErrors() | セッションにバリデーションエラーが存在しない |
assertSessionDoesntHaveErrors() | セッションにバリデーションエラーが存在しない |
assertSessionMissing($key) | セッションに指定したキーが存在しない |
ファイルアップロードのテスト
Illuminate\Http\UploadedFile クラスの fake() メソッドを使って、ダミーのファイルや画像を生成できます。
Storage ファサードの fake() メソッドと組み合わせることで、ファイルアップロードを簡単にテストできます。
assertMissing() を使います。
ダミーファイルのカスタマイズ
画像のサイズやファイルサイズを指定できます。バリデーションルールのテストに便利です。ビューのテスト
HTTPリクエストをシミュレートせずにビューを直接レンダリングしてテストできます。view() メソッドはビュー名とオプションでデータの配列を受け取り、Illuminate\Testing\TestView のインスタンスを返します。
TestView クラスでは以下のアサーションメソッドが使えます。
| メソッド | 説明 |
|---|---|
assertSee($value) | ビューに指定した文字列が含まれる |
assertSeeInOrder([...]) | ビューに指定した文字列が順番に含まれる |
assertSeeText($value) | ビューのテキストに指定した文字列が含まれる |
assertSeeTextInOrder([...]) | ビューのテキストに指定した文字列が順番に含まれる |
assertDontSee($value) | ビューに指定した文字列が含まれない |
assertDontSeeText($value) | ビューのテキストに指定した文字列が含まれない |
TestView インスタンスを文字列にキャストします。
withViewErrors() を使います。
コンポーネントのテスト
blade() メソッドを使って生のBladeテンプレート文字列をレンダリングできます。
component() メソッドを使ってBladeコンポーネントをレンダリングできます。Illuminate\Testing\TestComponent のインスタンスを返します。
レスポンスアサーション一覧
Illuminate\Testing\TestResponse クラスが提供する主要なアサーションメソッドです。
HTTPステータス
| メソッド | 説明 |
|---|---|
assertOk() | 200 OK |
assertCreated() | 201 Created |
assertAccepted() | 202 Accepted |
assertNoContent($status = 204) | 204 No Content |
assertBadRequest() | 400 Bad Request |
assertUnauthorized() | 401 Unauthorized |
assertForbidden() | 403 Forbidden |
assertNotFound() | 404 Not Found |
assertUnprocessable() | 422 Unprocessable Entity |
assertTooManyRequests() | 429 Too Many Requests |
assertInternalServerError() | 500 Internal Server Error |
assertStatus($code) | 指定したステータスコード |
assertSuccessful() | 2xx 系のステータスコード |
assertClientError() | 4xx 系のステータスコード |
assertServerError() | 5xx 系のステータスコード |
リダイレクト
| メソッド | 説明 |
|---|---|
assertRedirect($uri) | 指定したURIへリダイレクト |
assertRedirectContains($string) | リダイレクトURIに指定した文字列が含まれる |
assertRedirectToRoute($name, $params) | 指定したルートへリダイレクト |
assertRedirectToSignedRoute($name, $params) | 指定した署名付きルートへリダイレクト |
assertRedirectBack() | 直前のURLへリダイレクト |
コンテンツ
| メソッド | 説明 |
|---|---|
assertSee($value, $escaped = true) | 指定した値がレスポンスに含まれる |
assertSeeInOrder(array $values) | 指定した値が順番に含まれる |
assertSeeText($value) | 指定したテキストが含まれる |
assertDontSee($value) | 指定した値が含まれない |
assertDontSeeText($value) | 指定したテキストが含まれない |
assertContent($value) | レスポンスボディが指定した値に一致する |
assertDownload($filename) | ダウンロードレスポンスである |
JSON
| メソッド | 説明 |
|---|---|
assertJson(array $data) | JSONレスポンスが指定したデータを含む |
assertExactJson(array $data) | JSONレスポンスが指定したデータに完全一致する |
assertJsonPath($path, $value) | 指定したパスの値が一致する |
assertJsonMissingPath($path) | 指定したパスが存在しない |
assertJsonStructure(array $structure) | JSONが指定した構造を持つ |
assertJsonCount($count, $key) | 指定したキーのJSONが指定数の要素を持つ |
assertJsonFragment(array $data) | JSONに指定したフラグメントが含まれる |
assertJsonMissing(array $data) | JSONに指定したデータが含まれない |
assertJsonIsArray() | JSONがアレイである |
assertJsonIsObject() | JSONがオブジェクトである |
assertJsonValidationErrors($keys) | 指定したキーのバリデーションエラーが含まれる |
assertJsonMissingValidationErrors($keys) | 指定したキーのバリデーションエラーが含まれない |
ヘッダーとクッキー
| メソッド | 説明 |
|---|---|
assertHeader($headerName, $value) | 指定したヘッダーが存在する |
assertHeaderMissing($headerName) | 指定したヘッダーが存在しない |
assertCookie($name, $value) | 指定したクッキーが存在する |
assertCookieExpired($name) | 指定したクッキーが期限切れである |
assertCookieMissing($name) | 指定したクッキーが存在しない |
assertPlainCookie($name, $value) | 指定した暗号化されていないクッキーが存在する |
ビュー
| メソッド | 説明 |
|---|---|
assertViewIs($value) | 指定したビューが返された |
assertViewHas($key, $value) | ビューに指定したデータが存在する |
assertViewHasAll(array $data) | ビューに複数のデータが存在する |
assertViewMissing($key) | ビューに指定したデータが存在しない |
バリデーション
| メソッド | 説明 |
|---|---|
assertValid($keys) | 指定したキーにバリデーションエラーがない |
assertInvalid($keys) | 指定したキーにバリデーションエラーがある |
TDDを実践するためのポイント
Featureテストから始める
Featureテストから始める
HTTPテストは
tests/Feature/ ディレクトリに作成します。アプリケーションの外から見た動作(リクエスト→レスポンス)を最初に定義することで、実装すべき機能が明確になります。RefreshDatabaseを使う
RefreshDatabaseを使う
データベースを使うテストでは
RefreshDatabase トレイトを使いましょう。各テスト後にデータベースがリセットされ、テスト間でのデータ干渉を防げます。テストの独立性を保つことで、実行順序に依存しない安定したテストスイートが構築できます。ファクトリーを積極的に使う
ファクトリーを積極的に使う
User::factory()->create() のようなモデルファクトリーを使うと、テストデータの作成が簡単になります。特定の状態を持つモデルを作成するためにファクトリーの状態(state)を定義しておくと、テストの可読性が向上します。1テスト1アサーション
1テスト1アサーション
1つのテストメソッドではできるだけ1つのことを検証しましょう。テストが失敗したときに原因が特定しやすくなります。「Arrange(準備)→ Act(実行)→ Assert(検証)」のAAAパターンを意識するとテストが読みやすくなります。
認証テストを忘れない
認証テストを忘れない
認証が必要なルートには必ず「認証済みの場合」と「未認証の場合」の両方のテストを書きましょう。セキュリティ上の問題を早期に発見できます。
関連ページ
テスト入門
Laravelでのテストの基本的な書き方と
php artisan test の使い方を確認します。