PCOVでコードカバレッジ取得を高速化

この記事はCakePHP Advent Calendar 2019の21日目の記事です

つい先日、ついにCakePHP 4.0がリリースされましたが、CakePHP 4.0で利用しているテスティングフレームワークはもちろんPHPUnitです。CakePHP3では、PHPUnit 6.0系を使っていましたが8.5.0に更新されています。

PHPUnitで、コードカバレッジを取得するにはXdebugを使うのが定番ですが、PHPUnit8系ではXdebug以外にPCOVを利用することができます。

PCOVは、今年(2019年)リリースされたばかりのコードカバレッジドライバーで、高速かつ省メモリで動作することが特徴です。

ということで、今回は実際にどれくらい高速化できるのかを簡単に調べてみました。

計測した環境

当初、CakePHP3で作ったサンプルアプリをCakePHP4化して試そうと思っていたのですが、いろいろな問題があり断念しCakePHP4本体のテストの一部(CakePHPのUnitTestすべてを実行するとかなり時間がかかるので、ORMのテストのみ)を利用して計測しました。

計測した環境は、macOS上のDocker Containerで、PHP公式で公開されているこちらをベースに若干拡張などを追加したものを利用しています。

それぞれのバージョンは以下のとおりです。

# php -v
PHP 7.3.10 (cli) (built: Oct 10 2019 21:12:52) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.10, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.10, Copyright (c) 1999-2018, by Zend Technologies
# pecl list 
Installed packages, channel pecl.php.net:
=========================================
Package Version State
apcu    5.1.17  stable
pcov    1.0.6   stable
redis   5.0.2   stable
xdebug  2.9.0   stable    

コードカバレッジなし

まずは、Xdebugを無効にしてコードカバレッジなしでの計測結果がこちら。

# ./vendor/bin/phpunit tests/TestCase/ORM/
PHPUnit 8.5.0 by Sebastian Bergmann and contributors.

.............................................................   61 / 1331 (  4%)
.............................................................  122 / 1331 (  9%)
...
..................................................            1331 / 1331 (100%)

Time: 7.04 seconds, Memory: 36.00 MB

OK, but incomplete, skipped, or risky tests!
Tests: 1331, Assertions: 3917, Skipped: 3, Incomplete: 2.

Xdebug

Xdebugでコードカバレッジを取得した場合がこちら。

# ./vendor/bin/phpunit tests/TestCase/ORM/
PHPUnit 8.5.0 by Sebastian Bergmann and contributors.

.............................................................   61 / 1331 (  4%)
.............................................................  122 / 1331 (  9%)
...
..................................................            1331 / 1331 (100%)

Time: 3.68 minutes, Memory: 126.00 MB

OK, but incomplete, skipped, or risky tests!
Tests: 1331, Assertions: 3917, Skipped: 3, Incomplete: 2.

Generating code coverage report in Clover XML format ... done [1.68 minutes]

Generating code coverage report in HTML format ... done [1.8 minutes]

やはりかなり遅いですね。約31倍です。

PCOV

PCOVでの計測結果がこちら。

# php -d pcov.enabled=1 ./vendor/bin/phpunit tests/TestCase/ORM/
PHPUnit 8.5.0 by Sebastian Bergmann and contributors.

.............................................................   61 / 1331 (  4%)
.............................................................  122 / 1331 (  9%)
...
..................................................            1331 / 1331 (100%)

Time: 24.55 seconds, Memory: 126.00 MB

OK, but incomplete, skipped, or risky tests!
Tests: 1331, Assertions: 3917, Skipped: 3, Incomplete: 2.

Generating code coverage report in Clover XML format ... done [10.48 seconds]

Generating code coverage report in HTML format ... done [46.87 seconds]

なんと、Xdebugを使った場合と比べると約10分の1の時間で完了しています!カバレッジを計測していない場合と比べると、約3.5倍。Xdebugと比べると許容範囲かなと思います。しかも、メモリ使用量もXdebugと同じという結果でした

まとめ

まとめたものがこちら

実行時間 使用メモリ
カバレッジなし 7.04 s 36.00 MB
Xdebug 220.80 s 126.00 MB
PCOV 24.55 s 126.00 MB

実際のコードで実行時間に差は出るとは思いますが、かなりの高速化が期待できそうです。

CakePHP4へのアップデートはプラグインやライブラリの対応など、まだ色々とハードルはありますが、PHPUnitのバージョンアップはかなり魅力的だと思っています。PHPUnit自体の変更については全く追えていないので今後キャッチアップしていきたいと思っています。

参考