なぜテストを書くか
テストは、未来の自分とチームのための安全ネットです。
テストの種類(テストピラミッドで見る)
開発の流れの V 字でいう単体・結合・システムテストのうち、ここでは自動で回すものを扱います(E2E テストは、システムテストの一部を自動にしたもの、と考えると分かりやすい)。細かいテストほど速く安く、たくさん書けます。大きなテストほど安心感はありますが、遅く壊れやすいので少しだけにします。この形は Mike Cohn が 2009 年の本で示した「テストのピラミッド」です。段を押すと、中身が出ます。
書き方の基本
テストは「読まれるコード」です。落ちたときに、何が壊れたかすぐ分かるように書きます。
準備・実行・確認に分けた例(JavaScript)
Laravel(Pest)のテスト
Laravel には Pest と PHPUnit が最初から入っていて、php artisan test で動かせます(Laravel の公式の文書の例)。
Vitest のテスト
ファイル名に .test. か .spec. を入れると、テストとして見つけてくれます(Vitest の公式の始め方の例)。
テストデータの作り方(Laravel)
結合テストで最初に詰まるのが、「テストの前に、どんなデータを入れておくか」です。Laravel には、そのための道具がそろっています。
ファクトリーで、要る分だけ作る
$user = User::factory()->create(); // 1 人 $users = User::factory()->count(3)->create(); // 3 人 $user = User::factory()->unverified()->create(); // 状態を変えて
モデルごとに「ふつうの値」を決めておき、テストでは、確かめたい所だけを書きます。
テストごとに、データベースを空に戻す
use Illuminate\Foundation\Testing\RefreshDatabase; pest()->use(RefreshDatabase::class);
前のテストのデータが、次のテストに残らなくなります。テストの順番で結果が変わる、を防ぎます。
決まったデータは、シーダーで入れる
$this->seed(OrderStatusSeeder::class);
注文の状態の一覧のように、どのテストでも要るデータは、シーダーでまとめて入れます。
直す前に、そのバグで落ちるテストを書いておくと、直ったことと、もう戻らないことを確かめられます。デバッグの基本の流れの最後の歩(戻らないようにする)と同じ考えです。
出典: Laravel「Database Testing」 / Laravel「Eloquent: Factories」
練習: 境目(境界値)でバグを見つける
年齢で料金が決まる関数に、間違いが 1 つ隠れています。年齢を選んでテストを足し、仕様どおりか確かめてください。間違いの場所は「新しい問題」を押すたびに変わります。
| 年齢 | 仕様(期待) | 関数の答え | 結果 |
|---|
同じ扱いのグループと、境目の値
全部の年齢を試すことはできません。同じ扱いになる値をグループに分け(同値分割)、各グループから代表を 1 つ選びます。そのうえで、間違いが起きやすいグループの端(境界値)の前後を試します。
テストの代役(テストダブル)
本物のメール送信や外の API をテストで動かすと、遅く不安定で、ときには本当に送ってしまいます。本番の部品の代わりに置くものを、まとめて「テストダブル」(代役)と呼びます。この分け方は Gerard Meszaros の整理を、Martin Fowler が紹介したものです。
外のもの・時刻・乱数を固定する
カバレッジ(テストで通ったコードの割合)
テストを動かしたとき、コードのどれだけが実行されたかの割合です。Laravel なら php artisan test --coverage で出せます。
Martin Fowler は、カバレッジは「テストされていない所を見つけるには役に立つが、テストの良さを表す数字としてはほとんど役に立たない」と書いています。
上の練習で 3 歳・9 歳・30 歳・70 歳の 4 つだけを試すと、料金の関数の行はすべて通ります(カバレッジ 100%)。それでも、境目の間違いは見つかりません。大事なのは「何を確かめたか」です。
CI で毎回、自動で回す
テストは、書いても動かさなければ守ってくれません。プッシュやプルリクエストのたびに自動で全部動かし、落ちたらマージしないようにします。Git「チームの流れ」へ。
ときどき落ちる「不安定なテスト」
同じコードなのに、通ったり落ちたりするテストのことです。Google は 2016 年に、テストの実行のおよそ 1.5% が不安定な結果を出し、テストのほぼ 16% になんらかの不安定さがあると報告しています。
よくある原因
- テスト同士が、順番やデータを共有している
- 非同期の処理を待ちきっていない
- 外のサービスに本当につないでいる
- 今の時刻に頼っている
- 前のテストの後片付けができていない
どう扱うか
Martin Fowler は、不安定なテストを別の場所に「隔離」して、健康なテストの結果を信じられるようにすることを勧めています。ただし、隔離したテストはすぐに直します。消したり、放っておいたりはしません。
AI 時代のテスト
AI が書くコードが増えるほど、テストは「AI の仕事を確かめる道具」として大事になります。AI の機能そのもののテストには、ふつうのテストとは違う工夫が要ります。評価の体験はAI を組み込んだアプリのタブへ。
やりがちなミス(チェックリスト)
自分のテストで確かめたら、チェックを付けてみてください(この端末にだけ保存されます)。