こんにちは!日々の開発、本当にお疲れ様です。
PHPでの開発を進める中で、「自分が書いたテストコード、本当にアプリケーションの隅々まで網羅できているんだろうか?」と不安になったことはありませんか?「テストは通っているけれど、もしかしたら誰も通らない死んだコード(デッドコード)が放置されているかもしれない……」そんなエンジニアのモヤモヤを鮮やかに解決してくれるのが、今回ご紹介する Xdebug と PHPUnit を組み合わせた「コードカバレッジ(網羅率)測定」です。
これをマスターすると、テストの品質が数値として可視化され、自信を持ってデプロイできるようになります。今回は、まだXdebugやカバレッジ測定に触れたことがない方に向けて、ツールの本質から「Hello World」的な実践まで、優しく丁寧に紐解いていきますね。これを読めば、あなたの毎日のテスト駆動開発(TDD)やリファクタリングが劇的に安心で楽しいものになりますよ。
—
1. なぜ Xdebug とコードカバレッジが必要なのか?
デバッガーだけではない、Xdebugの本当の役割
多くの人は、Xdebugを「ブレークポイントを置いて変数の中身を覗き見るためのツール(ステップデバッガー)」だと思っています。もちろんそれも重要な機能ですが、Xdebugのもう一つの強力な顔が「コードの実行追跡(Tracing)とカバレッジ計測エンジン」です。
PHPはリクエストが終わるとメモリを解放して消えてしまうインタプリタ言語です。そのため、「どの行のコードが実行され、どの行が一度も通らなかったのか」を正確に知るには、PHPの実行エンジン(Zend Engine)の内部に入り込み、C言語レベルでフックをかける必要があります。それをやってくれるのがXdebugです。
カバレッジ(網羅率)とは何か?
コードカバレッジとは、「自動テスト(PHPUnitなど)を実行した際に、アプリケーション全体のコードのうち、何パーセントが実際に通過(実行)されたか」を示す指標です。
- 100%を目指すべきか?
実は、カバレッジ100%イコール「バグがない」ではありません。しかし、「テストされていないコード」をあぶり出すにはこれ以上ない最強の武器になります。
- リファクタリングの安全網
「この古いIF文、消しても大丈夫かな…?」と思った時、カバレッジを取っていれば、そのコードがテストから一度も呼ばれていない(=消しても影響がない)ことが一発で分かります。
—
2. 開発環境へのインストールと基礎セットアップ
それでは、実際に手を動かして環境を整えていきましょう。ここでは、現代のPHP開発のスタンダードであるDocker環境、あるいはローカル環境を想定して進めます。
ステップ1: Xdebugの導入(peclを使用)
お使いのPHPのバージョンに合わせて、Xdebugを拡張機能としてインストールします。ターミナルで以下のコマンドを実行してください(※環境に合わせて適宜読み替えてください)。
PECLを使ってXdebugの最新安定版をインストール
pecl install xdebug
ステップ2: `php.ini` の設定(ここが最重要!)
インストールが終わったら、PHPの設定ファイル(`php.ini` または `xdebug.ini`)に設定を追加します。「なぜこの設定が必要なのか」をコメントで解説しながら記述しますね。
[xdebug]
; 1. Xdebugの稼働モードを「開発・デバッグ・カバレッジ」すべてを網羅する設定にします
zend_extension=xdebug.so
xdebug.mode=debug,coverage
; 2. IDE(PhpStormやVS Codeなど)と連携するためのポート指定(デフォルトは9003)
xdebug.client_port=9003
xdebug.client_host=127.0.0.1
; 3. 自動でデバッグを開始させず、トリガーが引かれた時やCLI実行時に動くようにする
xdebug.start_with_request=yes
> 先輩からのアドバイス:
> カバレッジを計測する際は、必ず `xdebug.mode=coverage`(または `debug,coverage`)を指定する必要があります。この設定が抜けていると、PHPUnit側から「Xdebugが見つからないよ!」と怒られてしまうので注意してくださいね。
動作確認(Hello World的アプローチ)
正しくXdebugが有効化されたか、ターミナルで以下のコマンドを叩いて確認してみましょう。
php -v
実行結果のイメージ:
PHP 8.2.0 (cli) (built: Dec 8 2022 09:20:00) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.0, Copyright (c) Zend Technologies
with Xdebug v3.2.0, Copyright (c) Derick Rethans
このように、`with Xdebug v3.2.0` という文字が表示されていれば、第一関門突破です!
—
3. 実践!PHPUnit × Xdebug でカバレッジを測定する
ここからが本番です。実際に簡単なクラスとテストコードを用意し、カバレッジレポートを出力してみましょう。
ターゲットとなるクラス(Calculator.php)
今回は非常にシンプルな「計算機クラス」を題材にします。あえて、「まだテスト書いていない分岐(デッドコード)」を作っておきます。
テストコード(CalculatorTest.php)
次に、PHPUnit用のテストを書きます。ここでは `add` メソッドのテストだけを書き、`divide` メソッドのテストはあえて書きません。
assertSame(4, $calculator->add(2, 2));
}
// あえて divide のテストは書かない!
}
カバレッジレポートを出力するコマンド
それでは、PHPUnitを実行してカバレッジを測定しましょう。ターミナルで以下のようにコマンドを実行します。
vendor/bin/phpunit –coverage-text
実行されたターミナルのログ(イメージ):
PHPUnit 10.0.0 by Sebastian Bergmann and contributors.
Runtime: PHP 8.2.0 with Xdebug 3.2.0
. 1 / 1 (100%)
Time: 0.050 seconds, Memory: 6.00 MB
OK (1 test, 1 assertion)
Code Coverage Report:
2023-10-25 10:00:00
Summary:
Classes: 100.00% (1/1)
Methods: 50.00% (1/1) <-- おっと、メソッドの半分が未テスト!
Lines: 60.00% (3/5) <-- 全体の60%しか網羅されていない!
おぉっ、見事に結果が出ましたね!
テスト自体は「OK(成功)」していますが、コードカバレッジを見ると 60% しか網羅できていません。
—
4. 視覚的なHTMLレポートを出力して弱点を暴く
テキストベースだけでなく、ブラウザで「どの行がテストされていて、どの行がテストされていないか」を色付きで確認できる HTMLレポート を出力してみましょう。これが実務で一番よく使われる方法です。
1. PHPUnitの設定ファイル(`phpunit.xml`)に追記する
プロジェクトの根っこにある `phpunit.xml` に、カバレッジの出力先を設定します。
2. コマンドを実行してHTMLを生成する
設定ができたら、再度PHPUnitを走らせます。
vendor/bin/phpunit
生成された `reports/coverage/index.html` をブラウザで開いてみてください。
プロジェクト全体のファイル一覧が表示され、`Calculator.php` をクリックすると……なんと、テストされた行が「緑色」、テストされていない(スルーされた)行が「紅色(赤)」でハイライトされて表示されます!
「あ、`divide` メソッドの例外処理の部分が真っ赤だな。ここにテストケースを追加しよう」というネクストアクションが、直感的に一目でわかるようになります。この瞬間、開発の質がワンランク上がったことを実感できるはずです。
—
5. 現場で役立つ知見:パフォーマンスと向き合う心構え
最後に、現場でXdebugを扱う上での非常に重要な「知見」をシェアしておきます。
- カバレッジ計測は遅いという事実
XdebugはC言語で書かれて高速ですが、それでもコードの全行の実行を監視・記録(ログ生成)するため、テストの実行速度が通常の数倍〜十数倍に落ちることがあります。
- CI/CD(GitHub Actionsなど)での使い分け
毎回のローカルでの細かな修正時にはカバレッジを取らずに素早くテストを回し、「PR(プルリクエスト)を投げる時」や「CI環境」でだけカバレッジを測定するようにビルドスクリプトを分けるのが、開発スピードを落とさないプロの知見です。
—
まとめ
今回は、XdebugとPHPUnitを使ったコードカバレッジ測定の基本から実践までを解説しました。
1. Xdebugの `mode=coverage` を設定することで、PHPの内部エンジンから実行追跡が可能になる。
2. `–coverage-text` や HTMLレポート出力を使うことで、「どのコードがテストされていて、どこが放置されているか」が丸裸になる。
3. 可視化されたデータを元にテストを追加することで、リファクタリングや機能追加にビビらない強固なコードベースが手に入る。
これをマスターすれば、あなたの毎日のコーディングやテスト作成が、勘や経験に頼ったものから、データに裏打ちされた確信に満ちたものに劇的に変わりますよ。ぜひ今日の開発から取り入れてみてくださいね!