php7 + phpdbgで高速カバレッジ出力

先日は、今私が関わっているプロジェクトのphpのバージョンを挙げた際のTipsについて投稿しました。

http://blog.matchingood.com/entry/2017/03/09/202011blog.matchingood.com

今日は、php7にバージョンアップしたことによって可能になった、phpdbgによるコードカバレッジ出力について書きたいと思います。

phpdbgとは

Loading...

phpdbgは、phpのデバッガです。デバッガというとphpの場合似たようなものとしてxdebugもありますが、xdebugはあくまでphpの拡張モジュールであって、その恩恵を最大限に受けるにはIDEが必要不可欠です。

一方、phpdbgは端末上での逐次実行やブレークポイントの設定など、デバッガとしての実行を端末環境で行うことができます。C言語に馴染みがある人ならgdbライクだというとわかっていただけると思います。

phpdbgはphp5.6からphpのコアモジュールとして採用されており、phpがインストール済みなら既にインストールされています。

今回はphpdbgのデバッガとしての使用についてはひとまず置いておいて、このphpdbgを用いたカバレッジの出力についてご紹介したいと思います。

今までのコードカバレッジの出力

現在私が関わっているプロジェクトでは、CIでのテストの際にコードカバレッジを出力しています。PHPUnitを用いている場合は以下のようなコマンドです。

/path/to/phpunit --coverage-html=$CIRCLE_ARTIFACTS

これによって、$CIRCLE_ARTIFACTSの表すディレクトリにコードカバレッジがhtmlで出力されます。しかし、これがとても重い…

これまでのプロジェクト上のCI上のテスト(カバレッジ出力込)の実行時間について、過去の記録を調べてみました。CIはCircleCIを利用しています。

environment assertions time
php5.6 + phpunit 4.8.29 726 8m35s
php7.0 + phpunit 4.8.29 724 2m56s
php7.0 + phpunit 5.7.15 692 3m04s

php5.6時代は700程度のアサーションでも8分以上かかっています。それに対してphp7恐るべし…!php5.6に比べて約3倍の高速化です。phpunitのバージョンアップはLaravel5.4へのバージョンアップの際に行いましたが、これについてはあまり関係していなさそうです(むしろ遅くなってる?)

とはいえ、これらのテストはカバレッジを出力しなければ、どれも30秒程度で終わります。つまり、CIでのテストを高速化するならこのカバレッジ出力の部分を高速化したい!ということになります。これを叶えるのがphpdbgです。

phpdbgを用いたコードカバレッジ出力

従来のカバレッジ出力では、ドライバとしてxdebugを利用しています。このドライバをphpdbgに変更するには、先ほどのコマンドの先頭にphpdbg -qrrをつけるだけです。

phpdbg -qrr /path/to/phpunit --coverage-html=$CIRCLE_ARTIFACTS

phpdbgはphpのコアモジュールなので、phpにPATHが通っているならばphpdbgも通っていると思われるので、パスは省略しています。

phpdbgのコマンドオプションの説明についてはGoogle先生にお任せしますが、ここでの-qrrは、「起動時のタイトル・バージョン表示を省略し、引数に指定されたスクリプトを即時実行した後、phpdbgを終了する」という意味になります。

では、phpunitによるテスト+phpdbgによるカバレッジ出力の結果を、先ほどの結果と合わせて見てみましょう。

environment assertions time
php5.6 + phpunit 4.8.29 726 8m35s
php7.0 + phpunit 4.8.29 724 2m56s
php7.0 + phpunit 5.7.15 692 3m04s
php7.0 + phpunit 5.7.15 with phpdbg 682 37s

なんと軽々と1分を切っていきました。すさまじい速さです…

全体としても2分以上の短縮ができました。CIの高速化は熱心に取り組むにはややハードルの高いissueですが、この程度の変更で短縮できるならとても良いですね!

注意事項

phpdbgについては、php5.6からコアモジュールとして公式に配布されていますが、カバレッジの出力に関してはphp7からのサポートとなります。これについては、PHPUnitカバレッジ出力に利用しているPHP_CodeCoverageというコンポーネントの要件に依存しているためです。

最後に

コードカバレッジの出力をphpdbgを通して行うことで、CIの時間を2分以上早めることができました!導入も手軽なので、php7を用いたプロダクトでカバレッジ出力がしたいのならば是非おすすめしたい方法です!