Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

phpunit/php-code-coverageって何をしてるんだ #phperkaigi

phpunit/php-code-coverageって何をしてるんだ #phperkaigi

hideki kinjyo

March 08, 2024
Tweet

Resources

補足資料: OpCodeとカバレッジ計測の対応について

https://speakerdeck.com/o0h/phperkaigi-2024-omake

発表資料内で「別に展開している」と言及されている資料です

More Decks by hideki kinjyo

Other Decks in Programming

Transcript

  1. 自己紹介 • 金城秀樹 / きんじょうひでき • GitHub:@o0h / Twitter:@o0h_ •

    好きなFWはCakePHP • アイコンは 美味しい鮭親子丼の写真です
  2. 

  3. カバレッジの種類 • 一言で「カバレッジ」といっても、 観点によりいくつかの種類がある • PHPUnitのドキュメントでは 5種類のカバレッジに言及している • Line Coverage

    • Branch Coverage • Path Coverage • Function and Method Coverage • Class and Trait Coverage 7. Code Coverage — PHPUnit 11.0 Manual https://docs.phpunit.de/en/11.0/code-coverage.html 
  4. カバレッジの種類 • 一言で「カバレッジ」といっても、 観点によりいくつかの種類がある • PHPUnitのドキュメントでは 5種類のカバレッジに言及している • Line Coverage

    • Branch Coverage • Path Coverage • Function and Method Coverage • Class and Trait Coverage 7. Code Coverage — PHPUnit 11.0 Manual https://docs.phpunit.de/en/11.0/code-coverage.html  ココだけ おさらい してみましょう
  5.  PHPコード 実際のOpCode 1. 引数$xに値をセットする 2. 引数$yに値をセットする 3. $xをチェックして、 真ならJUMP→⑤へ

    4. $yをチェックする 5. おしまい! 見比べてみておくれ 見比べてみておくれ
  6. PHPUnitの起動〜テスト実行までの流れ テストケースの実行 個別のテストケースの管理 テスト一式の管理 全体の管理 PHPUnit\TextUI\ Application::run() vendor/bin/phpunit -> phpunit.php

    PHPUnit\TextUI\ TestRunner::run() PHPUnit\Framework\ TestSuite::run() PHPUnit\Framework\ TestCase::run() PHPUnit\Framework\ TestRunner::run() PHPUnit\Framework\ TestCase::runBare() PHPUnit\Framework\ TestCase::runTest() PHPUnit\Framework\ TestCase::{ケース}()  `phpunit`コマンドの実行から個別のテストケースが実行されるまでは、 ざっくりとこうした流れとなる
  7. PHPUnitの起動〜テスト実行までの流れ テストケースの実行 個別のテストケースの管理 テスト一式の管理 全体の管理 PHPUnit\TextUI\ Application::run() vendor/bin/phpunit -> phpunit.php

    PHPUnit\TextUI\ TestRunner::run() PHPUnit\Framework\ TestSuite::run() PHPUnit\Framework\ TestCase::run() PHPUnit\Framework\ TestRunner::run() PHPUnit\Framework\ TestCase::runBare() PHPUnit\Framework\ TestCase::runTest() PHPUnit\Framework\ TestCase::{ケース}()  「カバレッジ収集の初期設定」「(終了後)レポートデータの生成」を実行する
  8. PHPUnitの起動〜テスト実行までの流れ テストケースの実行 個別のテストケースの管理 テスト一式の管理 全体の管理 PHPUnit\TextUI\ Application::run() vendor/bin/phpunit -> phpunit.php

    PHPUnit\TextUI\ TestRunner::run() PHPUnit\Framework\ TestSuite::run() PHPUnit\Framework\ TestCase::run() PHPUnit\Framework\ TestRunner::run() PHPUnit\Framework\ TestCase::runBare() PHPUnit\Framework\ TestCase::runTest() PHPUnit\Framework\ TestCase::{ケース}()  「カバレッジ収集の開始」「終了」を実行する
  9. SebastianBergmann\CodeCoverage\Filter • `phpunit/php-code-coverage` のクラス • `phpunit.xml`に含まれる `source` > `include/exclude` に

    相当する情報を扱う • ここで集計対象となるファイルの列 挙・管理が行われる 
  10. PHPUnitの起動〜テスト実行までの流れ テストケースの実行 個別のテストケースの管理 テスト一式の管理 全体の管理 PHPUnit\TextUI\ Application::run() vendor/bin/phpunit -> phpunit.php

    PHPUnit\TextUI\ TestRunner::run() PHPUnit\Framework\ TestSuite::run() PHPUnit\Framework\ TestCase::run() PHPUnit\Framework\ TestRunner::run() PHPUnit\Framework\ TestCase::runBare() PHPUnit\Framework\ TestCase::runTest() PHPUnit\Framework\ TestCase::{ケース}()  タイミングとしては、ここで行われる (`CodeCoverage::instance()->init()`と同じ箇所からの起動)
  11. 使い方 (execute) • `phpcov execute $PHP_SCRIPT` で、 その$PHP_SCRIPTの実行によって、 カバーされたコードを分析する •

    仕組みはシンプルで、 `\SebastianBergmann\CodeCoverage\CodeCoverage::start()` を実行した後に $PHP_SCRIPTをproxy、実行後に `CodeCoverage::stop()`してレポートを生成 • Options • `—include`: 集計対象に含めるパス • `—html` `—text` `—php` `—clover` (など): 出力するレポート形式・出力先 • `—path-coverage`: パスカバレッジ分析の実行 
  12. 使い方 (merge) • `phpcov merge $DETA_DIR_PATH` で、 $DETA_DIR_PATHに含まれている 複数のカバレッジデータを合成した 解析結果レポートを出力する

    • 合成のものとになるのは `—php`の形式で、拡張子を`.cov`で揃えたもの • PHP形式=`SebastianBergmann\CodeCoverage\CodeCoverage`オブジェクトの serialized文字列 • Options • `—html` `—text` `—php` `—clover` (など): 出力するレポート形式・出力先 
  13. 他にも色々とアイディアはあるはず・・ • テストコード自体のカバレッジ • 「実は動いていないテストコード」があったら消したい • Property based testingやMutation testingとの組み合わせ

    • 肝要なのは、 「どうやって起動・終了させるか」「集めたデータがどんな値を持っ ているか」「それを組み立てるツールの存在と使い方」 を知ること • 基本さえ掴んでしまえば、自身のニーズに合わせて活用が効く!
  14. 使い方 (patch-coverage) • コードの変更差分に対して、 行カバレッジの統計を出す機能 • `phpcov patch-coverage --path-prefix $INCLUDE_PATH_PREFIX

    $COVERAGE_DATA $PATCH`で実行 • 出力はテキスト形式のみで、高機能なレポートは提供しない • その代わり、include/exclude等の詳細なオプションを必要としない
  15. 例えば、の使い方 • CIとは相性良さそう • GitHub Actionsに組み込めば 「カバーされていない行にコメント」とか出来そう? • 「diffにある指定の行に指摘をする」は、提供されているAPI経由で行える •

    過去に書いた記事(情報が古い可能性があります、確認していません!!) > PHPUnitの実行結果(失敗したテスト)をProblem MatcherでPRのdiffに示す https://daisuki.nichiyoubi.land/entry/phperkaigi-2022-lt-hosoku
  16. カバレッジの種類 • 一言で「カバレッジ」といっても、 観点によりいくつかの種類がある • PHPUnitのドキュメントでは 5種類のカバレッジに言及している • Line Coverage

    • Branch Coverage • Path Coverage • Function and Method Coverage • Class and Trait Coverage 7. Code Coverage — PHPUnit 11.0 Manual https://docs.phpunit.de/en/11.0/code-coverage.html 
  17. 

  18. 

  19. Class and Trait Coverage • クラス・トレイトの内で 1メソッド以上実行された割合 • 自前のメソッドの実行が条件 •

    継承元への転送ではダメ • コンストラクタも除く • 右のスニペットは、 カバレッジが2/3になる • クラス`C`は カバーされていないとみなされる 
  20.