Laravel のログのテスト用ライブラリ Log fake が 2.0 にバージョンアップしていたので紹介します。
Log fake って何?
Laravel のログのテスト用ライブラリで、主に以下のようなことができます。
- ログの内容やログレベルに対してアサーションが書ける
- テストでログのファイルが生成されなくなるため気づいたらゴミが貯まっていたということを避けられる
Laravel ではMail::fake()
を使うと、テストの間はメールが実際に送られることがなくなり、メールの中身をテストすることもできるようになります。
それのログ版だと考えてもらえれば理解が早いと思います。
使い方
2.0 以降がサポートしているバージョンは以下の通りで、少し新しいですのでその点はご注意ください。
- PHP 8.0, 8.1
- Laravel 9.0
インストール
まずは以下のコマンドでインストールしましょう。
composer require timacdonald/log-fake --dev
準備
Mail::fake()
のようにテストの先頭やsetUp()
に以下を書きます。
新しいバージョンでは少しシンプルに書けるようになっていました。
// 旧バージョン
Log::swap(new LogFake());
// 新バージョン
LogFake::bind();
基本のアサーション
- ログレベル: error
- ログの内容に特定の文字列が含まれている
例えば上記を確認するアサーションを書くと以下のようになります。
// 旧バージョン
Log::assertLogged('error', function ($message) use ($exceptionMsg) {
return Str::contains($message, $exceptionMsg);
});
// 新バージョン
Log::assertLogged(function (LogEntry $log) use ($exceptionMsg) {
return $log->level === 'error'
&& Str::contains($log->message, $exceptionMsg);
});
LogEntry というクラスが以下のプロパティ(他にもあります!)を持っています。
- level:ログレベル
- message:ログの内容
以前はログレベルをアサーションメソッドの引数として指定していましたが、新バージョンではコールバック関数の中で上記のプロパティを使ってまとめてチェックするようになっています。
ログレベルは気にしないけど内容だけ確認したい場合などは今のほうがシンプルに書けるかもしれません。
ただ、エラー文の完全一致であれば以前はassertLoggedMessage()
でシンプルに書けたのでこういう書き方も残しておいてほしかった気もします。
これくらいならラップして独自にメソッドを追加すればいいよねというスタンスなのかもしれません。
// 新バージョンではなくなっているアサーション
Log::assertLoggedMessage('error', $expectedMessage);
他のアサーション
ほとんどは上記のアサーションで足りると思いますが他の使いやすそうなアサーションを独断と偏見で挙げていきます。
ログの回数をチェック
特定のログが指定の回数出力されているかを確認できます。
Log::assertLoggedTimes(
fn (LogEntry $log) => $log->message === 'hogehoge',
2 // 第2引数で回数を指定
);
チャンネルを指定してチェック
特定のチャンネルに対してのアサーションは、チャンネルを指定した後にチェーンメソッドで続けて書けるようです。
Log::channel('slack')
->assertLogged(fn (LogEntry $log) => $log->message === 'hogehoge');
ログ内容を出力する Log::dump()
これが新バージョンで一番便利になった点かなと思ってます!
テストを書いてる最中でアサーションが通らないとき、そもそもログが吐かれていないとか別のエラーで落ちてるなどはあるあるかと思います私だけ?
そこでLog::dump()
をすれば以下のようにログの内容を出力してくれるのでデバッグに役立ちます!
array:1 [ // vendor/timacdonald/log-fake/src/ChannelFake.php:52
0 => array:5 [
"level" => "error"
"message" => "エラーが発生しました。"
"context" => array:1 [
"id" => 100000000
]
"times_channel_has_been_forgotten_at_time_of_writing_log" => 0
"channel" => "daily"
]
まとめ
ログが意図した通りに出力されているかテストしたい場合に、わざわざログのファイルを取得して〜というのはかなり手間になってしまうと思います。
Log fake を使えば他の Laravel のファサード同様にシンプルにテストできるようになるのでおすすめです!
今回はバージョン 2.0 を紹介しましたが、PHP や Laravel のバージョンが要件を満たしていない場合は 1.X 系を使っても十分に役目は果たせると思いますのでぜひ使ってみてください。