このスライドは、「PHP カンファレンス Japan 2020」で登壇した時に使用したスライドです。
テストピラミッドを意識したテストコード実装戦略PHP Conference Japan 2020Track4-3-B #track4-3-b-test-pyramid02
View Slide
Who’s 02?名前: 02 (大津和槻)Twitter: @cocoeyes02職業: Webエンジニア(主にバックエンド)経歴:PHPカンファレンス2019 登壇「PHPerのためのテストコード入門」
今回の登壇で話すこと● テストピラミッドについて解説● テストピラミッドを意識しながら、実際にLaravelとPHPをバージョンアップした事例共有
今回の登壇で話さない(話せない)こと● どのプロダクトにも適応できるテストコード実装戦略
今回のゴールテストコード実装戦略実例を通して、テストピラミッドについて理解が深められること
アジェンダ● テストピラミッドとは?● 各層のテストの紹介● 実例:Laravelチュートリアルのバージョンアップ
テストピラミッドとは?
ユニットテスト統合テストテストピラミッドとは?Mike Cohn氏が”Succeeding with Agile”で最初に提唱した3つのテストのコストと実装すべきテスト量を 示したものUIテストコスト大小実装すべきテスト量小多
ユニットテスト統合テストテストピラミッドとは?コスト● 実行時間● テスト範囲● 修正工数○ メンテナンス○ テスト失敗時の原因特定UIテストコスト大小実装すべきテスト量小多
ユニットテスト統合テストテストピラミッドとは?実装すべきテスト量● テストのケース量○ 正常系・異常系○ パターンテスト結果(成功/失敗)がわかるまでかかる時間≒実行時間×テストケース量UIテスト実装すべきテスト量小多コスト大小
フィードバックループフィードバックを得るまでにかかる時間を図示したもの「テスト結果(成功/失敗)がわかるまでかかる時間」がそのまま「フィードバックを得るまでにかかる時間」になるwikipedia "Extreme programming"https://en.wikipedia.org/wiki/Extreme_programming
フィードバックループフィードバックを得るまでにかかる時間を図示したもの「テスト結果(成功/失敗)がわかるまでかかる時間」がそのまま「フィードバックを得るまでにかかる時間」になる→コストが少ないテストの方が、 生産性↑に繋がりやすいwikipedia "Extreme programming"https://en.wikipedia.org/wiki/Extreme_programming
各層のテストの紹介
ユニットテスト統合テスト各層のテストの紹介● UIテスト● 統合テスト● ユニットテストUIテストコスト大小実装すべきテスト量小多
ユニットテスト統合テストUIテスト最もユーザ目線に近い。Webサービスではブラウザを自動操作し、 期待通りの動作をしているか検証するSeleniumなどを利用したE2Eテストがこれに当たる。UIテストコスト大小実装すべきテスト量小多
ユニットテスト統合テスト統合テスト特定のインプットを渡し返ってきた内容が 正しいかどうかを検証Featureテスト(Laravelのhttpテスト)や、WebAPIを使ったテストはこれに当たるUIテストコスト大小実装すべきテスト量小多
ユニットテスト統合テスト統合テスト特定のインプットを渡し返ってきた内容が 正しいかどうかを検証Featureテスト(Laravelのhttpテスト)や、WebAPIを使ったテストはこれに当たるUIテストコスト大小実装すべきテスト量小多値、リクエストなど
ユニットテスト統合テストユニットテスト一つの関数やメソッドに対して、I/Oを通して 仕様通りの挙動をしているか検証するPHPでは、PHPUnitを使う例が多いUIテストコスト大小実装すべきテスト量小多
実例題材LaravelチュートリアルのバージョンUP
Laravel Tutorial
Laravel Tutorial● 超シンプルなTODOリストサービス○ 新規登録○ ログイン○ ログアウト○ パスワードリセット○ タスク追加○ タスク削除● Laravel 5.2 / PHP5.6● 典型的なMVC
ユニットテスト統合テストLaravel Tutorial実装されているテストコードはfeatureテスト(統合テスト)のみ● TOP画面が開ける● 新規登録できる● タスク作成/削除ができる● 他人のタスクは見れない● 他人のタスクの削除はできないUIテスト
ユニットテスト統合テストLaravel TutorialPHPUnitを使っている(v4.8.36!)● 実行時間は2秒ほどUIテスト
Laravel Tutorial● 「本番でバグが出ていることに気づかなかった」という状況を回避しつつ、「LaravelTutorial」をバージョンアップしたい● バージョンアップ時にエラーが発生する場合は、いち早く気づけるようにしたい
テストピラミッドに合わせた方針候補● 保険としてUIテストを追加する● 一部設計を修正してから、ユニットテストを追加する
保険としてのUIテストを追加する● ユーザー目線からのテスト(UIを含めてのテスト)も書いて、さらに担保している感を強めたい○ FWのバージョンアップは、どこにバグが現れるかわからない○ テストコードというのは、自分が書いたコードに自信を持つことも目的の 1つ● 「全てUIテストで書く」ことはしない○ 一番ユーザー目線に近いテストなので安心度があるが、全部 UIで書くとテスト時間が長くなる■ 数十分、数時間かかるテストは運用するの辛い■ 統合テストよりは少なくするユニットテスト統合テストUIテスト
保険としてのUIテストを追加する● 今回はseleniumを採用○ Laravel DuskはLarvael5.4からなので、今回は使えない○ ChromeやFirefoxなどクロスブラウザでのテストができる余地を残しておく● 新規登録→ログアウト→ログイン→タスク登録のUIテストを作成した○ 実行時間は30秒ユニットテスト統合テストUIテスト
一部設計を修正してからユニットテストを追加する● 統合テストでカバーできていないテストは、ユニットテストで担保したい○ バリデーション○ モデル● 一部リファクタリングをして、DBの処理などをモック化できるようにするユニットテスト統合テストUIテスト
一部設計を修正してからユニットテストを追加する● 自分のタスクを一覧表示する機能をリファクタリング○ 一覧表示するときの条件をクエリで決めるのではなく、 Collectionのメソッドを使って決めるようにした○ ユニットテスト時には、「 Collectionのメソッドを使って決めた」部分だけテストすれば良いユニットテスト統合テストUIテスト
一部設計を修正してからユニットテストを追加する● 新規登録時のバリデーションパターンを網羅● タスク作成時のバリデーションパターンを網羅● 自分のタスクを一覧表示する機能のロジックをテスト● 実行時間は全部合わせて3.5秒ぐらいユニットテスト統合テストUIテスト
Laravel Tutorial バージョンアップの結果は…?● Laravel 5.2->5.3○ 全層のテストコードでエラーを発見した● Laravel 5.3->5.4○ UIテストのテストコードだけエラーを発見した( viewのキャッシュをクリアするコマンド実行が必要だった)○ あとはテストコードの修正をした● Laravel 5.4->5.5, PHP5.6->7.0○ 全層のテストコードでエラーを発見した● Laravel 5.5->5.6, PHP7.0 -> PHP7.1○ 全層のテストコードでエラーを発見した
Laravel Tutorial バージョンアップの結果は…?● Laravel 5.2->5.3○ 全層のテストコードでエラーを発見した● Laravel 5.3->5.4○ UIテストのテストコードだけエラーを発見した( viewのキャッシュをクリアするコマンド実行が必要だった)○ あとはテストコードの修正をした● Laravel 5.4->5.5, PHP5.6->7.0○ 全層のテストコードでエラーを発見した● Laravel 5.5->5.6, PHP7.0 -> PHP7.1○ 全層のテストコードでエラーを発見した→いちいち画面を見ることなく、バージョンアップの作業にもくもくできた
最後に● どのテストも銀の弾丸というわけではない○ それぞれ長所短所がある● テストどの層でどの範囲を担保するのか、すり合わせることが大事○ 全体を俯瞰して、どの機能がどのテストで担保できているのか見る必要がある
参考文献など● 今回検証に使った環境○ https://github.com/cocoeyes02/laravel_test_pyramid● 参考文献○ 初めての自動テスト ――Webシステムのための自動テスト基礎○ https://www.oreilly.co.jp/books/9784873118161/