第16回: Contractテストで実装差し替えに備える — 「切り替えても安全だ」と言えることのおろそか?
インターフェース(Contract)を定義する目的の一つは、実装を差し替えても挙動が変わらないことの保証です。この保証をテストで固定しなければ、RedisからMemcachedへ切り替えたときにどこかで微妙な差异が発生するリスクがあります。
Category
インターフェース(Contract)を定義する目的の一つは、実装を差し替えても挙動が変わらないことの保証です。この保証をテストで固定しなければ、RedisからMemcachedへ切り替えたときにどこかで微妙な差异が発生するリスクがあります。
Repository層は永続化ロジックの契約層です。上位層がRepositoryの返却仕様に依存するため、返却値の型やフィルタリングの挙動をテストで固定することが重要です。
assertStatus(200) で満足しているテストは、「リクエストがおそらく到達した」ことを確認しているだけです。その後のDBの状態・レスポンスのJSON構造・リダイレクト先まで検証することで初めて「機能が正しく動いた」と言えます。
「同じロジックだが入力値だけ変わるテスト」が何度もコピペースされている――境界値テストでよく起きるこの状態は、Pestのデータセット機能で訐決できます。
Laravel Octaneはアプリを常駐化して後続リクエストを高速に底だけるパワーツールです。用い方を注意しないと、リクエスト間で状態が漏れる深刻な問題が起きます。「「導入したのにおかしい挙動が起きる」」の大半はこの状態漏れです。
「Unitテストが全部緑なのにリファクタ後に本番でバグが起きた」――これは、実装詳細をテストしていて、ユーザーが実際に使う流れ をテストしていなかったために起きます。
Queueのワーカーが死んでジョブが溢れている状態で、ユーザーから「メールが来ない」と見つかるまで数分かかることがあります。Laravel Horizonは、Queueの状態をリアルタイムで見るダッシュボードを提供し、そうした盲点を排除します。
外部APIへの接続が一時的に失敗したとき、ジョブがそのまま消えてしまう――これはジョブの 失敗設計がない 状態で起きる定番の事故です。「たまに失敗する」と「常に失敗する」の間にある状態を放置すると、運用後に大きな手戻りを召います。
「ログインしているのに自分の記事が削除できてしまった」「管理者のみ操作できるはずなのに他のユーザーも操作できた」――認可の実装漏れは進次的なセキュリティリスクを生みます。
「一覧画面を開くたびに遅い」「本番だとタイムアウトする」――注意してログを見ると、発行されているSQLが数百件、なんてことがあります。これがN+1問題です。「記事数だけSQLが発行される」状態で、テーブルが増えるほど効果が大きくなります。