LaravelでPHPUnitを使ったテスト駆動開発の方法

by

in

Laravelでテスト駆動開発をする際の環境構築として初期設定をまとめていきます。

テストの実行方法、記述方法、テスト用のデータベース設定までまとめていきます。

なお、Laravel 11系からはテストフレームワークの Pest に対応するようになってますが、Laravelを新しく立ち上げた時にデフォルトで設定されているのは PHPUnitなので、デフォルト設定で手軽に使える方法かなとPHPUnitの解説をしていきます。

とりあえずテストを実行してみる

Laravelはプロジェクト作成時からすでにテストが作成されているため、簡単に実行する事ができます。

$ composer create-project laravel/laravel example-app
$ cd example-app
$ php artisan --version
Laravel Framework 11.8.0
$ php artisan test

   PASS  Tests\Unit\ExampleTest
  ✓ that true is true

   PASS  Tests\Feature\ExampleTest
  ✓ the application returns a successful response                                                                                              0.07s  

  Tests:    2 passed (2 assertions)
  Duration: 0.11s


# phpunitコマンドでテストの実行も可能
$ ./vendor/bin/phpunit
PHPUnit 11.1.3 by Sebastian Bergmann and contributors.

Runtime:       PHP 8.2.19
Configuration: /path/to/example-app/phpunit.xml

..                                                                  2 / 2 (100%)

Time: 00:00.058, Memory: 26.00 MB

OK (2 tests, 2 assertions)

簡単ですね。

用意されているのはクラスファイル等の挙動を確認する Unitテストと、HTTPレスポンスを模倣して実際のWebブラウザで表示される内容を確認する Featureテストが用意されています。

作成済みのファイルはこちら

ポイントとしては

  • Unitテストは use PHPUnit\Framework\TestCase; を継承
  • Featureテストは use Tests\TestCase; を継承

している点です。この違いで実行できる処理が変わります。

データベースの書き込みをテスト

前述の内容は公式ドキュメントにもありますが、データベースの書き込みをテストする際に問題が発生した経験があります。

(後述する Environment の項目にはありますが、これがデータベースに関係する事だったというのは初見では解りづらいかと感じます。)

機能的には準備されてはいるので、私なりに解釈した使い方をまとめていきます。プロジェクトによっては別の使い方をしているかもしれませんので、他の方法をご存知の方は使いやすい方を選択してください。

.env.testing の用意

まずは、テスト実行時のデータベース環境を用意します。

$ cp .env .env.testing

.env.testingphpunit.xml ファイルに記述されている

<env name="APP_ENV" value="testing"/>

によって決定したファイル名です。環境変数 APP_ENV の値によって .env.〇〇 が読み込むものが決定します。

ただし、.env の設定値はキャッシングされる対象になっているため、場合によってはキャッシングの削除が必要です。

# .env をキャッシングするコマンド (通常は開発環境での実行は必要無い)
$ php artisan config:cache
or
$ php artisan optimize

# .env のキャッシングを削除するコマンド
$ php artisan config:clear
or
$ php artisan optimize:clear # 開発環境ではこれで全てのキャッシュを削除するのがオススメ

要するに phpunit.xml の設定で .env.testing を読み込む設定になっていても、既存の .env でキャッシングされている内容の方が優先されるので config:clear を実行することが推奨されます。

( 自分の環境で発生していた問題の原因が公式で言及されていたこれだったと気づくのに結構時間がかかりました )

この場合に問題になるのは気軽に phpunit の実行をしてしまうと開発中の画面で表示されているテストデータが消えてしまう場合が考えられます。自分で操作するテストデータと、テストコードで確認するためのテストデータの保存先は分けておくのが無難です。

テスト環境のデータベースを準備

.env.testing にテスト環境のデータベースを作成する設定を追加します。

~~~ 中略 ~~~

DB_CONNECTION=sqlite
# DB_HOST=127.0.0.1
# DB_PORT=3306
DB_DATABASE=/path/to/example-app/database/database.testing.sqlite
# DB_USERNAME=root
# DB_PASSWORD=

~~~ 中略 ~~~

今回はsqliteでテスト用のデータベースを設定しましたが、公開環境と同じデータベース環境を用意しましょう。mysqlで公開しているのであれば テスト用のデータベースも mysqlにします。

データベースについてのテストコードは公式のページを参照してください。

https://laravel.com/docs/11.x/database-testing

この記事ではテスト用の環境を作成することを優先しているため、Laravel公式の会員登録機能をまとめた Jetstreamで作成されるテストコードで確認します。

# jetstreamの設定
$ composer require laravel/jetstream
$ php artisan jetstream:install livewire

# この段階でテストを実行するとデータベースファイルが存在しないエラーになります
$ php artisan test
Database file at path [/path/to/example-app/database/database.testing.sqlite] does not exist.

sqliteで設定したデータベースファイルが存在しないので作成と、マイグレーションの実行をします。

コマンドラインで実行する際には --env=testing を使用することで .env.testing のファイルを読み込んでからコマンドの処理を実行します。

$ php artisan migrate --env=testing

   WARN  The SQLite database configured for this application does not exist: database/database.testing.sqlite.  

  Would you like to create it? (yes/no) [yes]
❯ yes

   INFO  Preparing database.  

  Creating migration table ............................................................................................................. 6.25ms DONE

   INFO  Running migrations.  

  0001_01_01_000000_create_users_table ................................................................................................. 5.20ms DONE
  0001_01_01_000001_create_cache_table ................................................................................................. 1.40ms DONE
  0001_01_01_000002_create_jobs_table .................................................................................................. 3.95ms DONE
  2024_05_26_023445_add_two_factor_columns_to_users_table .............................................................................. 1.58ms DONE
  2024_05_26_023458_create_personal_access_tokens_table ................................................................................ 1.84ms DONE

これでテストを実行することができます。

$ php artisan test

   PASS  Tests\Unit\ExampleTest
  ✓ that true is true

   WARN  Tests\Feature\ApiTokenPermissionsTest
  - api token permissions can be updated → API support is not enabled.                                                                         0.11s  

   PASS  Tests\Feature\AuthenticationTest
  ✓ login screen can be rendered                                                                                                               0.04s  
  ✓ users can authenticate using the login screen                                                                                              0.03s  
  ✓ users can not authenticate with invalid password                                                                                           0.01s  

   PASS  Tests\Feature\BrowserSessionsTest
  ✓ other browser sessions can be logged out                                                                                                   0.03s  

   WARN  Tests\Feature\CreateApiTokenTest
  - api tokens can be created → API support is not enabled.                                                                                    0.01s  

   PASS  Tests\Feature\DeleteAccountTest
  ✓ user accounts can be deleted                                                                                                               0.02s  
  ✓ correct password must be provided before account can be deleted                                                                            0.01s  

   WARN  Tests\Feature\DeleteApiTokenTest
  - api tokens can be deleted → API support is not enabled.                                                                                    0.01s  

   WARN  Tests\Feature\EmailVerificationTest
  - email verification screen can be rendered → Email verification not enabled.                                                                0.01s  
  - email can be verified → Email verification not enabled.
  - email can not verified with invalid hash → Email verification not enabled.

   PASS  Tests\Feature\ExampleTest
  ✓ the application returns a successful response                                                                                              0.01s  

   PASS  Tests\Feature\PasswordConfirmationTest
  ✓ confirm password screen can be rendered                                                                                                    0.01s  
  ✓ password can be confirmed                                                                                                                  0.01s  
  ✓ password is not confirmed with invalid password                                                                                            0.22s  

   PASS  Tests\Feature\PasswordResetTest
  ✓ reset password link screen can be rendered                                                                                                 0.02s  
  ✓ reset password link can be requested                                                                                                       0.03s  
  ✓ reset password screen can be rendered                                                                                                      0.02s  
  ✓ password can be reset with valid token                                                                                                     0.02s  

   PASS  Tests\Feature\ProfileInformationTest
  ✓ current profile information is available                                                                                                   0.02s  
  ✓ profile information can be updated                                                                                                         0.01s  

   WARN  Tests\Feature\RegistrationTest
  ✓ registration screen can be rendered                                                                                                        0.01s  
  - registration screen cannot be rendered if support is disabled → Registration support is enabled.                                           0.01s  
  ✓ new users can register                                                                                                                     0.01s  

   PASS  Tests\Feature\TwoFactorAuthenticationSettingsTest
  ✓ two factor authentication can be enabled                                                                                                   0.05s  
  ✓ recovery codes can be regenerated                                                                                                          0.07s  
  ✓ two factor authentication can be disabled                                                                                                  0.03s  

   PASS  Tests\Feature\UpdatePasswordTest
  ✓ password can be updated                                                                                                                    0.02s  
  ✓ current password must be correct                                                                                                           0.02s  
  ✓ new passwords must match                                                                                                                   0.02s  

  Tests:    7 skipped, 25 passed (46 assertions)
  Duration: 0.94s

これでテスト駆動開発用のデータベースを設定することができました。あとはテストコードをプロジェクトに合わせて記述していきましょう。

テストコードを書いていると、どうしても書けない処理、解りづらい内容になってしまうかと思います。その場合にはモックを使う事で解決できるかもしれません。モックについては以下の記事で解説しています。

終わりに

以上、Laravelのテスト駆動開発をする際に必要になるPHPUnitの環境構築でした。

他にも、こちらの記事で chromium-driver が実行できるようになったので、今後はレンタルサーバー内でもLaravelDuskを実行してブラウザテストも出来るようにしていきたいですね。

https://renpro.muchuu.net/2022/08/15/レンタルサーバーでselenium-puppeteerを動かす/

参考

Laravel で PHPUnit 実行時に .env.testing を見てくれない?
https://qiita.com/shohei_ot/items/de6e2da7ac0c9741904a

レンタルサーバーを最大限使いこなすための方法

Laravelの記事を厳選して紹介

投稿者


Comments

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA