Laravelにはデフォルトで組込まれており、インストールしてすぐにでも使用する事が出来ます。今回は、LaravelとPHPUnitを使ってテストを書きつつ、データアクセス部分のモック化を行いながらHTTPテストやユニットテストの効率化を行っていきます。開発環境は以下の通りです。3.7今回はユニットテストとHTTPテストをメインに見ていきますが、その中でDBテスト部分にも触れるのでデータソースを2つ用意しています。記事中のパスの表記について、Laravelのプロジェクトルートを「laravel/」としています。HTTPテストとユニットテストユニット(単体)テストは、1つの機能に対する自動テストの事を指します。1つのメソッドだったり関数だったりに対して行うテストです。対してHTTPテストは、HTTPリクエストから始まる各機能の繋がりやその結果(レスポンス)など、一連の流れをテストするものです。HTTPテストはFeatureディレクトリへ、ユニットテストはUnitディレクトリへ設置します。ユニットテストと言われるfunctionベースのテストが自動テストの基本ですが、HTTPテストも取り入れる事によってもっと包括的なテストを実行する事ができ、よりアプリケーションの信頼度も高まります。そんな中、ただテストを定義していけば良いかというとそうでもありません。一定規模のアプリケーションになると、機能の数も増え、全てのテストを回すだけで結構な時間がかかってしまいます。テストの時間を短くし、効率よく開発を進める為に「モック」という手法が自動テストではポイントになってきます。その辺を踏まえながら今回は一連のテストを定義していきたいと思います。今回、テストを行うアプリケーションのサンプルとして、以下の構成のものを使用します。本情報の一覧を取得するアプリケーションの機能です。1つのコントローラから1つのサービスクラスを通じてリポジトリからデータを取得する流れになっています。HTTPテスト本来は小さい単位のテストから作成していくのがセオリー(なのでHTTPテストは通常ユニットテストの後で定義)ですが、今回のメインテーマはモックなので、敢えてメインディッシュであるHTTPテストから定義します。以下、コントローラのソースです。}}このindexメソッドに対するテストを定義します。エンドポイントはドメインルート(https://xxx.xxx.com/)です。Factory定義まずはFactoryを編集して、モック化に使用する疑似データを定義しておきます。Factoryは以下artisanコマンドで生成できます。BookFactory生成したBookFactoryに以下を追加します。'test_book_mock_data_1');コントローラのテストここからHTTPテストを定義していきます。以下のartisanコマンドを叩いてテストクラスを生成します。}}コンストラクタであるsetUpメソッドで、データアクセス部分のモック化を行っています。'test_book_mock_data_1')->make()->toArray();先にFactoryで定義した疑似データを取得し、BookListの疑似データを作成しています。$this->repositoryMock);リポジトリへのデータアクセスをモック化しています。データアクセスに対するモックを作成リポジトリのgetList()メソッド要求に対して、BookListの疑似データを返す様に指定データアクセスに対してモック化を実行これでデータアクセス部分のモック化が実行されます。次に各テストケースですが、HTTPテストなので、リクエストを発生するところからがスタートになります。今回定義したテストケースではそれぞれ、ドメインルートへのリクエストに対して以下のテストケースを定義しています。「ドメインルートへのリクエストをBookListコントローラが受け取り、Bookサービスクラスがリポジトリよりデータを取得しそれをビューへ渡す」という一連の処理の流れをテストする事ができるわけです。今回定義した2つのテストケースによって、きちんと意図した処理の道筋を通る事を確認する。これがHTTPテストを行う意味です。ストレージ部分はモック化し、そこの部分はリポジトリのユニットテスト(DBテスト)で行う事で、自動テストを効率化(時間短縮)する事ができます。今回の例でもしデータアクセス部分をモック化しない場合はリポジトリからのデータアクセスが発生するので、テスト用のDBやデータを用意する必要があります。前処理が必要になるので、それならばモック化した方が良い事しかありません。ユニットテストユニットテストでも必要な部分をモック化していきます。今回の例でいうとサービスクラスです。逆に、リポジトリのユニットテストの場合はがっちりデータベースと通信してCRUDのテストを行います。サービスクラスのテストテスト対象であるBookServiceクラスは以下のようなソースになっています。}}定義されているgetList()メソッドは、リポジトリから取得したデータをエンティティに渡しBookListオブジェクトを作成して返す処理になっています。このメソッドに対するユニットテストを定義します。以下のartisanコマンドを叩いてテストクラスを生成します。}}モック化の手順は先程と同じなので、バリエーションとしての紹介です。テストしたい部分になります。データアクセス部分はモック化し、その処理が正しく行えているかだけをテストしている。リポジトリのテストリポジトリでは実際にデータの操作を行う部分なのでモック化はせず、実際にDBを操作してテストを行います。今回はMySQLとSQLiteでのデータソースを用意していたので、この2つのリポジトリに対するテストを定義します。テスト対象となるインターフェースと各リポジトリのソースです。}}これらに対してテストを定義します。以下のartisanコマンドを叩いてテストクラスを生成します。--unitそれぞれ、テストを定義していきます。}}ちなみにデータソースが2つありますが、それぞれのテストDBを用意しています。.env.testingDB_DATABASE=test_laravel_dbDB_DATABASE_SQLITE=/path/to/laravel/database/test_database.sqliteテスト実行すべてのテストを定義したので、実際に走らせてみます。assertions)すべてのテストに合格した事を確認できました。まとめ以上で作業は終了です。ない部分はモック化する事で結構な時間を削る事ができます。「そのテストケースのあるべき姿」は常に追求していきたいですね。BookmarkLINELaravel&CircleCIで継続的インテグレーション。ユニットテスト、静的コード解析、E2Eテストなど。SESを使ってAPIメール送信を行う(Mailableクラス&SimpleEmailService)2019.12.3MySQL8.0.16で追加されたCHECK制約を試してみる。RitoLaboこのサイトについて利用規約プライバシーポリシ。