PHPUnitでLaravelのAPIをユニットテストする
読む所要時間: 15 分
アプリケーションを正常に動作させるためのベストプラクティスとして、テストがあります。指定されたソフトウェア要件が正しく実装されているかを確認するためのユニットテスト、自動機能テスト、APIエンドポイントテストの実施などです。プロジェクトで変更を実施した場合や、新たな機能を実装した場合でも、これらのテストを行うことにより、アプリケーションの動作不良を確実に回避できます。このような開発方法をテスト駆動開発と呼びます。
人気のあるPHPフレームワークであるLaravelも、テストの容易さを念頭に構築されており、PHPUnitというテストスイートが付属しています。PHPUnitはPHP開発者の生産性を向上するテストフレームワークです。ユニットテストと呼ばれる最小単位のコンポーネントでPHPコードをテストすることを主な目的として設計されていますが、ユニットテスト以外のテストにも柔軟に応用することができます。
このチュートリアルでは、テスト駆動開発の手法に従い、Laravel APIプロジェクトのエンドポイントをテストする方法について説明します。まず、失敗する前提のテストを記述します。その後、テストに合格するコードを記述します。チュートリアルを最後まで進めると、基本的なテストの実施方法について学び、新規または既存のLaravel APIプロジェクトに応用できるようになります。
必要条件
このチュートリアルを進めるにあたり、Laravelを使用したアプリケーション構築の基礎知識があると役立ちます。また、依存関係を管理するために、グローバルにComposerがインストールされている必要があります。
はじめに
Laravel APIを使用し、世界の大手テクノロジー企業に所属するCEOのリストを作成し、情報を表示します。過去のブログ記事「Build a Secure API in PHP Using Laravel Passport」で類似のAPIを構築しました。
できるだけ簡単に進められるようスタータープロジェクトをダウンロードします。このプロジェクトには、アプリケーションが適切に動作するための骨組みがあらかじめ用意されています。
まず、Gitを使用してスタータープロジェクトをダウンロードします。以下のコマンドを実行してください。
次に、新しいプロジェクトのフォルダーに移動し、 必要な依存関係をすべてインストールします。
このサンプルプロジェクトには、以下の内容が含まれています。
- ユーザーやCEOのモデルと、それぞれの
fillable
プロパティ - コントローラー、マイグレーションファイル、routes/api.phpファイルに含まれるAPIルート
- プロジェクトで動作するようにインストールされ、設定されたLaravel Passport。Laravel APIのセキュリティの確保については、「Getting Started with Unit Testing a Laravel API using PHPUnit」を参照してください。
次に、プロジェクトのルートディレクトリに.envファイルを作成し、.env.exampleファイルの内容を入力します。手作業で入力するか、または以下のコマンドを実行してください。
このプロジェクトのLaravelアプリケーションキーを生成します。以下のコマンドを実行してください。
プロジェクトを実行します。以下のコマンドを実行してください。
http://localhost:8000にアクセスすると以下のようなホームページが表示されます。
新しくインストールされたLaravelプロジェクトのデフォルトページなので、簡単な内容のみが表示されています。
データベースのセットアップ
テストを開始するには、テストデータベースのセットアップが必要です。このチュートリアルは、インメモリのSQLiteデータベースを使用し、シンプルな構造で進めていきます。また、このデータベースには、テストスクリプトを高速に実行できるメリットがあります。
databaseフォルダーにtest.sqliteファイルを作成してください。このファイルは、メインのデータベースとは別に設定を保持するために用意するものです。テストデータベースとやり取りを行う際に使用します。次に、.env
ファイルの.env.testing
にあるデータベース環境変数を以下のように置き換えてください。
それぞれのテストを行う前に、マイグレーションが必要になります。各テストの前にマイグレーションを実行し、テスト用のデータベースを正しく構築する必要があります。
マイグレーションの設定を行います。tests/TestCase.phpファイルにあるベースのTestCase
クラスを開き、以下のように内容を更新してください。マイグレーションの設定を行います。
ここでは、DatabaseMigrations
トレイトを組み込み、passportをインストールするためのArtisan
の呼び出しを追加しています。
最後に、PHPUnitを実行します。ターミナルで以下のコマンドを実行してください。
以下のような結果が表示されます。
上記の出力では、2つのテストが正常に実行されたことが分かります。これらはLaravelによりデフォルトでインストールされたテストです。後でこれらを変更します。
PHPUnitの実行コマンドを紐付けるために、composer.jsonファイルを開き、
scripts
に以下のようにテストコマンドを追加してください。
これで、composer test
を実行するとテストコマンドを実行できるようになりました。
CEOファクトリーの作成
Laravelのファクトリーは、FakerPHPライブラリを使用してテスト用のランダムデータを生成できる便利な機能です。Laravelには、User
クラス用のファクトリー定義があらかじめ読み込まれています。
CEO
クラス用のファクトリーを生成します。以下のコマンドを実行してください。
これにより、CEOFactory.phpという新しいファイルがdatabase/factoriesフォルダー内に作成されます。CEOFactory.phpファイルを開き、以下の内容をペーストしてください。
CEO
テーブルのフィールド指定と、Fakerライブラリの使用により、すべてのフィールドで正しい形式のランダムデータを生成します。
最初のテストの記述
前述したように、テストを記述します。その前に、tests/Featureフォルダーとtests/Unitフォルダーにある2つのサンプルのテストファイルを削除してください。
最初に、認証プロセスのテストを記述します。認証プロセスでは、登録とログインの処理が行われます。APIフォルダーには、この目的で作成されたコントローラーがすでに用意されています。
AuthenticationTestファイルを作成します。以下のコマンドを実行してください。
これにより、test/FeatureフォルダーにAuthenticationTest.phpファイルが作成されます。
AuthenticationTest.phpファイルを開き、以下の内容に置き換えてください。
このファイルには、以下のテストが記述されています。
testRequiredFieldsForRegistration
: 登録プロセスに必要なすべてのフィールドが正しく入力されているかテストします。testRepeatPassword
: パスワードは繰り返し入力する必要があります。最初入力したパスワードと同じ文字列を確認用のパスワードとして入力しなければ、このテストに合格することはできません。testSuccessfulRegistration
: ユーザーが正しくサインアップできるように、ダミーのデータに基づきユーザーが作成されます。
PHPUnitを使用してテストを実行します。以下のコマンドを実行してください。
以下のような結果が表示されます。
まだ機能を実装していないため、これは想定内の結果です。
app/Http/Controllers/API/Auth/AuthController.phpを開き、以下のように内容を更新してください。
testMustEnterEmailAndPassword()
メソッドを用いて、ユーザーが必須フィールドを空にしていないか確認するテストも作成しています。testSuccessfulLogin()
メソッドでは、ユーザーが正常に認証されるよう、ダミーユーザーを作成しました。
composer test
を使用して再度テストを実行します。予想どおり、このテストも失敗します。テストに合格するように、AuthController.phpファイルを以下のように更新してください。
合計で、5つの異なる重要なテストを記述しました。一部のテストケースには、APIからのレスポンスのステータスとjson()
構造が含まれています。
次のセクションでは、CEOエンドポイントに対して一連のテストを作成します。
CEOエンドポイントのテストの記述
このセクションでは、まずCEOエンドポイントのテストスクリプトを格納する新しいテストファイルを作成します。
以下のコマンドを実行してください。
このコマンドにより、tests/FeatureフォルダーにCEOTest.phpという新しいテストファイルが作成されます。このファイルを開き、以下の内容に置き換えてください。
複雑そうに見えるかもしれませんが、先ほど記述したテストと似た内容です。詳しく見てみましょう。
2つの異なるメソッドを作成しました。
testCEOCreatedSuccessfully
: 適切なデータを使用してCEOレコードを作成できるかテストします。testCEOListedSuccessfully
: 作成されたCEOのリストを取得し、レスポンスとして返すことができるかテストします。
AuthenticationTest
とは異なり、CEOTest
はauth:api
というミドルウェアにより保護されたエンドポイント向けに記述されています。新たに作成したダミーユーザーが認証を受けた後にエンドポイントにアクセスするよう、$this->actingAs($user, 'api')
を使用してこのユーザーを認証、認可した後に、CRUD(作成、読み取り、更新、削除)処理を実行します。
再度テストを実行します。composer test
を実行してください。
今回もテストに失敗しました。もうテストに失敗した理由はお分かりかと存じます。まだこれらのテストのロジックを学習中の方のために説明すると、テストに合格するには、CEOController.phpファイルに適切なコードを入力する必要があります。
CEOControllerの更新
app/Http/Controllers/API/CEOController.phpファイルを開き、以下のように内容を更新してください。
ここでは、新しいCEOのレコードを格納するメソッドと、データベースからCEO
のリストを取得するメソッドを作成しています。
テストを再度実行すると、今回は合格します。
最後に、特定のCEOの詳細情報を取得、更新、削除するテストを追加しましょう。CEOTest.phpファイルを開き、以下のメソッドを追加します。
上記のテストでは、適切なHTTP動詞(GET
、PATCH
、DELETE
)を使用し、api/ceo
エンドポイントにパラメーターとして一意のid
を渡すことにより、特定のCEO
レコードを対象に操作を行います。
次に、新しいテストも合格するようにCEOControllerファイルを更新します。app/Http/Controllers/API/CEOController.phpを開き、以下のメソッドを追加してください。
ここで作成したメソッドは、データベースにあるCEOのレコードを取得、更新、削除します。
最後にcomposer test
コマンドでテストを実行すると、以下の出力が表示されます。
まとめ
このチュートリアルでは、テスト駆動開発の手法を使用し、Laravel APIプロジェクトのエンドポイント向けのテストをご紹介いたしました。テスト駆動開発では、機能を追加したとしても、新たな実装は既存のコードベースの機能に一切影響を与えることがありません。ユーザーにも大きなメリットをもたらします。
チュートリアルの全コードはGitHubから入手できます。ぜひコードを分析して考察したり、このコードにテストを追加し、そのテストに合格するコードを記述してみてください。
Olususi Oluyemi氏はテクノロジー、プログラミング、Web開発の熱心な愛好家で、最先端のテクノロジーに強い関心を持っています。
- Twitter: https://twitter.com/yemiwebby
- GitHub: https://github.com/yemiwebby
- Webサイト: https://yemiwebby.com.ng/