3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

PHPUnit の processIsolation と log4php の LoggerAppenderConsole の相性が悪いので直す

Last updated at Posted at 2023-03-09

TL;DL

タイトル通り、PHPUnit+log4phpは相性が悪く動かない可能性があります。
回避策として 直接LoggerAppenderConsoleを修正する LoggerAppenderEchoを利用するかprocessIsolationを無効にします。
できればlog4phpを使わないようにしたほうがいいと思います。

発生条件

  • PHPUnitを使用している
    • オプションでprocessIsolationを有効にしている
  • テスト対象、またはテストでlog4phpを使用している
    • かつ、LoggerAppenderConsoleを使用している

何が起こるの?

サンプルプロジェクトをおいておきました。
こちらを実施すると画像のようなエラーになります。

Screen Shot 2023-03-09 at 13.01.43.png

なんで発生する?

log4phpの実装が悪いです。

PHPUnitのprocessIsolationを有効にしていると、子プロセスのテスト結果がシリアライズされて、標準出力経由で親プロセスとやりとりされます(エラーでブワーッと出てしまっているのはこのシリアライズされた値です)。

通常、テスト中に出力された文字はバッファされて適切に扱われるのですが、log4phpが標準出力されるべき値を上書いてしまう場合があります。

vendor/apache/log4php/src/main/php/appenders/LoggerAppenderConsole.php
 class LoggerAppenderConsole extends LoggerAppender {

	/** The standard otuput stream.  */
	const STDOUT = 'php://stdout'; // <- ここが原因!

どうすれば直る?

log4phpを使わない!(暴論)
すでにlog4phpプロジェクトは動いていなく、Issue,PRも何年も放置されています…(なので記事にしました)
また、PHP8.1以降ではDeprecatedとなりまともに動かせなくなります…

processIsolationを無効にするのもOKだと思います。

とはいえ、大人の事情ですぐに対応できないという場合もあるかもしれません。
そのような場合はこうします。

vendor/apache/log4php/src/main/php/appenders/LoggerAppenderConsole.php
 class LoggerAppenderConsole extends LoggerAppender {

	/** The standard otuput stream.  */
	//const STDOUT = 'php://stdout';
	const STDOUT = 'php://output';  // <- 'php://output'にする!

(2023/03/17 追記)

この修正をすることでテストは動くようになりますが、LoggerAppenderConsoleを利用しているWEBアプリ側でログがechoされてしまうようになりました。
なので、LoggerAppenderConsoleが強制的に'php://stdout'を指定しているのは正しい動きになり、この修正は適当ではないです。

環境変数などを用いてテストのみLoggerAppenderConsoleではなく代わりにLoggerAppenderEchoを利用するような作りにするのが妥当だと思います。

'php://output'?

公式を見てみるとこんな使い分けになっています。

php://output
php://output は書き込み専用のストリームで、 print および echo と同じ方法での出力バッファへの書き込みを許可します。

print()echo()は、特に何もしていなければ標準出力に、ob_start()などでバッファリングを有効にしている場合はバッファに書き込むようになります。

対して、php://stdoutまたは定数STDOUTを指定して出力した場合、 バッファリング中だったとしても、強制的に標準出力に文字を吐き出します

なので、processIsolation有効時、本来はPHPUnitのシリアライズされた結果が欲しいのですが、log4phpによって余計な文字が付いてきたり上書きされてしまったりしてデシリアライズできなくなるみたいです。

おまけ

まだまだlog4php使われていそうですね…

Screen Shot 2023-03-09 at 13.30.03.png

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?