本文へ移動

ホーム / Web / 第5部 品質と運用

第5部 品質と運用・第13章

テスト

★★☆ 重要6トピック・面接 3問

変更を怖がらずに出せるよう、テストをどう書くかを押さえる。

ひとことで

単体テストを多く、E2E テストは重要な流れだけ。速くて安定したテストを中心にする。

テストには粒度の違う種類があり、速くて安いものを多く、遅くて壊れやすいものを少なくする形をテストピラミッドと呼びます。

速くて安いテストを多く、遅いテストは要所だけE2E結合API + 本物の DB単体関数・部品大事な流れだけ効果が高いことが多いたくさん上ほど遅く、壊れやすく、費用が高い
テストピラミッド
種類確かめるもの速さ道具の例
単体テスト関数・クラス・1つの部品ミリ秒Vitest・Jest・RSpec・pytest
結合テストAPI と DB をつないだ動き、部品の組み合わせ数十ms〜秒本物の DB(コンテナ)で API を呼ぶ、Testing Library
E2E テストブラウザで画面を操作し、全部を通した流れ秒〜分Playwright・Cypress
スナップショットテスト出力(描画結果・JSON)が前回と同じか速いJest・Vitest の toMatchSnapshot、画像の比較

Web のバックエンドでは、本物の DB を使った API の結合テストが一番費用対効果がよいことが多く、ピラミッドの真ん中を厚くする考え方(テストトロフィー)もあります。スナップショットは、変化に気づく用途には便利ですが、差分を確かめずに更新しがちなので、大きなスナップショットは避けます。

面接ではこう答える

テストピラミッドは、速くて安い単体テストを多く、遅くて壊れやすい E2E テストを少なくする形の考え方です。Web のバックエンドでは、本物の DB を使った API の結合テストが一番費用対効果がよいことが多く、真ん中を厚くする考え方もあります。大事なのは、入力に対する結果を確かめるテストにし、実装の中身に依存させないことです。

ひとことで

本物の DB を立てて API を HTTP から呼ぶ結合テスト。SQL・制約・権限まで確かめられ、Web のバックエンドで効果が高い。

本物の DB を立てて、HTTP で叩いて、結果を確かめるDB を起動コンテナ・テスト用 DBデータを用意テストごとに作るAPI を呼ぶHTTP の層から結果を確かめる応答と DB の中身
結合テストの流れ

Web のバックエンドで費用対効果が高いのは、本物の DB を使って API を HTTP の層から呼ぶテストです。SQL の間違い・制約・トランザクションの動きまで確かめられます。

工夫やり方
DB を用意するCI でコンテナ(Testcontainers・サービスコンテナ)を起動し、マイグレーションを流す
テストを独立させるテストごとにトランザクションを張って最後に戻す、または表を空にする
速くするDB は1回だけ起動し、テストを並列に。データは必要な分だけ
確かめるステータス・応答の形(仕様のスキーマ)・DB に残った行・送ったジョブ

「他人のデータは 404」「同時に2回送っても1件」のような、権限と競合のテストもこの層で書けます。

面接ではこう答える

Web のバックエンドでは、本物の DB を使って API を HTTP の層から呼ぶ結合テストを中心にしています。DB をモックにすると、SQL の間違いや一意制約、トランザクションの動きが確かめられないからです。CI ではコンテナで DB を起動してマイグレーションを流し、テストごとにデータを作って独立させます。権限のテストや二重送信のテストもこの層で書きます。

モックにするのは、自分で制御できない外側だけ本物を使う・DB・自分のコードの関数・クラス・同じリポジトリのモジュール置き換える・決済・メールなど外部 API・時刻・乱数・遅い・お金がかかるもの
モックにするものと、しないもの

モックは、外部 API や時刻のように、テストで本物を使えないものの代わりです。何でもモックにすると、

  • 実装の中身(どの関数を何回呼んだか)を確かめるテストになり、リファクタリングのたびに壊れる。
  • モックと本物の動きがずれていて、テストは通るのに本番で壊れる(DB の制約・SQL の間違いはモックでは見つからない)。

DB は本物(Docker のコンテナ・テスト用の DB)を使い、モックにするのは自分で制御できない外部(決済・メール・時刻・乱数)だけにします。外部 API は MSW などで HTTP の層で置き換えると、実装に依存しにくくなります。テストは「入力に対する結果」を確かめるように書きます。

13.4E2E テストと待ち方

用語★★☆ 重要
ひとことで

ブラウザを動かしてユーザーの操作を再現する(Playwright など)。不安定にならない書き方が大事。

E2E テストは、本物のブラウザを動かして、ログイン・購入・登録のような大事な流れが通しで動くかを確かめます。遅くて壊れやすいので、全部の画面ではなく、壊れると困る流れに絞ります。

待ち方

不安定なテスト(たまに落ちる、flaky)の原因の多くは待ち方です。

要素が 3.5 秒後に出たとき0秒1秒2秒3秒4秒5秒要素が出る固定で 3 秒待つ待つまだ出ていないのに進む → 失敗見えるまで待つ自動で待つ出たらすぐ進む
固定の秒数で待つか、条件で待つか
// よくない:決まった時間だけ待つ
await page.waitForTimeout(3000);
// よい:見えるまで自動で待つ(Playwright)
await page.getByRole('button', { name: '購入する' }).click();
await expect(page.getByText('注文が完了しました')).toBeVisible();
  • 固定の秒数で待たず、「要素が見える」「通信が終わる」を条件に待つ。Playwright の locator と expect は自動で待ってくれる。
  • 要素は CSS のクラスより、役割とラベル(getByRole・getByLabel)で探す。見た目の変更で壊れにくく、アクセシビリティの確認にもなる。

面接ではこう答える

E2E テストは、本物のブラウザを動かして、ログインや購入のような大事な流れが通しで動くかを確かめるテストです。遅くて壊れやすいので、壊れると困る流れに絞ります。不安定になる原因の多くは待ち方で、固定の秒数ではなく、要素が見えるなどの条件で待ちます。要素は CSS のクラスより、役割とラベルで探すと、見た目の変更で壊れにくくなります。

順番を入れ替えても、並列でも通るように悪い例・前のテストが作ったデータに頼る・共有のユーザーを使い回す・毎回画面からログイン良い例・テストごとに API で準備・名前に一意の値を付ける・storageState を使い回す
テストデータの作り方
  • テストごとに必要なデータを API や DB の準備スクリプトで作り、他のテストに依存しない。順番を入れ替えても、並列に動かしても通るようにする。
  • ユーザー名などに一意の値を付け、同時に動くテストとぶつからないようにする。
  • ログインは毎回画面で行わず、一度ログインした状態を保存して使い回す(Playwright の storageState)。
  • 外部の決済などはテスト用の環境かモックにする。
ひとことで

たまに落ちるテストは、結果への信頼を壊す。リトライで隠さず、記録して隔離し、待ち方やデータの原因を直す。

不安定なテストは、隔離して必ず直す失敗トレース・動画を残すリトライで通った「不安定」と記録隔離必須から外して起票原因を直す待ち方・データ
不安定なテストの扱い方
  • プルリクエストごとに、プレビュー環境や CI の中で起動したアプリに対して流す。
  • ブラウザのインストールをキャッシュし、テストを分割して並列で動かす(シャーディング)。
  • 失敗したときのスクリーンショット・動画・トレースを成果物として残す。
  • 自動のリトライは1回程度にとどめ、リトライで通ったテストは「不安定」として記録して直す。不安定なテストを放っておくと、誰も結果を信じなくなります。
不安定さの原因直し方
固定の秒数で待つ条件で待つ(見える・通信が終わる)
テストどうしがデータを共有テストごとにデータを作る
アニメーション・時刻アニメーションを止める、時刻を固定する
外部サービスモックかテスト用の環境に

面接ではこう答える

不安定なテスト、いわゆる flaky なテストは、同じコードでも通ったり落ちたりするテストです。放っておくと、本当の失敗も「またか」と無視されるようになります。リトライは1回程度にとどめ、リトライで通ったものは不安定として記録し、必須のチェックから一時的に外して起票し、原因を直します。原因の多くは固定の秒数で待つこと、テストどうしのデータの共有、時刻やアニメーションです。

この章のまとめ

🖨 まとめシート(印刷・PDF)
  • テストピラミッドと、何をどの粒度でテストするか
  • E2E テストを安定させる工夫
  • テストの種類とピラミッド:単体テストを多く、E2E テストは重要な流れだけ。速くて安定したテストを中心にする。
  • 本物の DB を使った API のテスト:本物の DB を立てて API を HTTP から呼ぶ結合テスト。SQL・制約・権限まで確かめられ、Web のバックエンドで効果が高い。
  • E2E テストと待ち方:ブラウザを動かしてユーザーの操作を再現する(Playwright など)。不安定にならない書き方が大事。
  • CI での実行と不安定なテスト:たまに落ちるテストは、結果への信頼を壊す。リトライで隠さず、記録して隔離し、待ち方やデータの原因を直す。

この章のクイズ

面接ではこう聞かれる

まず答えを見ずに声に出して答え、そのあと開いて比べる。

Q1どんな方針でテストを書いていますか?

模範回答

費用対効果で粒度を選ぶようにしています。業務のルールや計算のように分岐が多いものは、速い単体テストで細かく確かめます。バックエンドの API は、本物の DB をコンテナで動かした結合テストを中心にしていて、SQL や制約の間違いまで見つけられるので一番効果が高いと感じています。E2E はログインや購入のような、壊れると困る流れだけに絞ります。

モックは決済やメールのような外部と、時刻だけにして、実装の中身ではなく入力と結果を確かめるように書きます。バグを直すときは、まずそれを再現するテストを書いてから直します。不安定なテストは放置せず、原因を直すか消して、CI の結果を信じられる状態を保つようにしています。

深掘りされたら

  • テストのカバレッジは目標にしていますか?

見られているポイント費用対効果で粒度を選んでいるか

Q2E2E テストがたまに落ちる(不安定な)とき、どう直しますか?

模範回答

多くの原因は待ち方とテストデータです。まず失敗したときのトレースやスクリーンショットで、どこで何が起きていたかを確かめます。決まった秒数だけ待っている所は、「要素が見える」「通信が終わる」を条件に待つ書き方に変えます。Playwright の locator と expect は自動で待ってくれます。

次に、テスト同士がデータを共有していないかを見ます。前のテストが作ったデータに依存していたり、並列で同じユーザーを使っていたりすると、順番によって落ちます。テストごとに必要なデータを作り、一意な名前を付けます。リトライで通ったテストも記録して直し、放置しないようにします。

深掘りされたら

  • 要素は何で探すのがよいですか?

見られているポイント待ち方とデータの独立、放置しない

Q3モックはどこまで使いますか?

模範回答

自分で制御できない外部だけに使います。決済サービス、メール送信、外部の API、現在時刻や乱数などです。DB は本物を使います。モックにすると、SQL の間違いや一意制約の違反など、本番で起きる問題がテストで見つからないからです。DB はコンテナで動かせば十分速く動きます。

また、「この関数が何回呼ばれたか」を確かめるテストは、実装を変えるたびに壊れるので、入力に対する結果を確かめるように書きます。外部の API は、HTTP の層で置き換える MSW などを使うと、呼び出し方に依存しにくくなります。

深掘りされたら

  • DB を使うテストを速く保つ工夫は?

見られているポイント外部だけをモックにする理由