読者です 読者をやめる 読者になる 読者になる

はむはむエンジニアぶろぐ

このブログのコンセプトは"ハッキングの為なら愛する家族を傷つけることをいとわない" 自分にとってエンジニアリングは "手段ではなく生きる目的" である

PHPUnitでカバレッジテストをやってみる

PHP PHPUnit テスト

f:id:secret_hamuhamu:20150404170600p:plain
タイトルの通り、PHPUnitカバレッジテストをやってみる。
Xdebugが必要なので、事前にインストールしておいてください。

環境構成

カバレッジテストとは?

英語で、Coverage Testと書き、どれ位テスト対象をカバーできているのかをカバレッジ率を確認します。
カバレッジテストが具体的にどのようなテストかというと、以下のフローチャートの① ~ ⑤ を網羅しているか、カバレッジ率を出します。

f:id:secret_hamuhamu:20150527005341p:plain

カバレッジテストを知らなくても、if文を知っていればこのプログラムちゃんフローチャート通りに分岐されるんだっけというのを考えたことがあるはずです。
カバレッジテストは、ホワイトボックステストと呼ばれる分類で、カバレッジ率(最大100%)が高いほど品質の良いコードであるが、 必ずしも100%にする必要はなくプロジェクト単位で、n%カバーできていればOKというような、みなしかたをします。


PHPUnitとかで使ったことある人は、わかると思いますが assertSame などを使ってオールグリーンにしようというものは、ブラックボックステストと呼ばれる分類です。

カバレッジテストでは、②の方に分岐されるという事が分かれば良くて、 例えば num1 の値が、99だったとして②に分岐してしまうバグを発見するものではありません。
どういう条件だったら分岐しますという境界値は、仕様の話なのでブラックボックステストで行います。

実際にやってみる

Coverage.php というクラスと CoverageTest.php というテストを作成します。

Coverage.php

<?php

class Coverage
{
    public function hoge($num1, $num2)
    {
        $x = 1;

        if ($num1 >= 100) {
            $x = $x + 1;
        }

        if ($num2 >= 100) {
            $x = $x * 2;
        }

        return $x;
    }
}


CoverageTest.php

<?php
require_once 'Coverage.php';

class CoverageTest extends PHPUnit_Framework_TestCase
{
    /**
     * @test
     */
    public function テスト()
    {
        $c = new Coverage();
        $c->hoge(100, 100);
    }
}


カバレッジテストでは、テスト対象のメソッドから期待通りの戻り値が返ってくるかテストしません。
あくまで、先ほどのフローチャートをカバーできたかどうかに関心があります。

では、カバレッジをとってみる。

phpunit --coverage-html dir CoverageTest.php

--coverage-html とすることで、dir ディレクトリにカバレッジレポートをHTML形式で、作成してくれます。
f:id:secret_hamuhamu:20150527005349p:plain

100%カバレッジです。
お気づきかもしれませんが、先ほどのフローチャートの③ と ⑤ の分岐がカバーされていないのに100%になっています。
これは、 ステートメント(処理)カバレッジ であるためです。
先ほどの、hogeメソッドに無駄なelse文を付け加えて再度、カバレッジをとり直すと88.89%に変わります。

    public function hoge($num1, $num2)
    {
        $x = 1;

        if ($num1 >= 100) {
            $x = $x + 1;
        } else {
          $x = $x;
        }

        if ($num2 >= 100) {
            $x = $x * 2;
        }

        return $x;
    }


ステートメントカバレッジとは?

実行可能な行が実行されたかどうか?というのをカバレッジします。
PHPUnitでは、Line Coverageというらしい。

実際にやりたいのは、Branch Coverageというもので、if文(分岐)が真の時と偽の時のパターンをカバーできているかどうか?というのをカバレッジします。
PHPUnitは、PHP_CodeCoverageというカバレッジライブラリを使っているが、残念ながらBranch Coverageに対応していないらしい。

注記 オペコードカバレッジ、 ブランチカバレッジ、 パスカバレッジ については、 PHP_CodeCoverage ではまだサポートしていません。

オペコードカバレッジとブランチカバレッジがあれば、先ほどのカバレッジ漏れは防げます。


まとめ

カバレッジ率が高ければ高いほど、品質が良いコードである。
しかし、カバレッジ率を気にするあまり設計が歪んでしまうのは本末転倒なので、カバレッジ率は目安程度に考えると良い。
カバレッジテストでは、仕様のテストではない。仕様のテストはブラックボックステストである。

カバレッジとることで、ブラックボックステストで漏れていたテストケースを発見出来るかもしれない。
ここの処理通ってないけど、テストどうなってるの?という気づく機会になる。

とはいえ、何が何でもカバレッジをとるというのは、大変だしカバレッジもメンテナンスするのかよっていう話にもなるので、要所要所で使えれば効果的に働くかな?と思います。

最近読んだ本

JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)

JUnit実践入門 ~体系的に学ぶユニットテストの技法 (WEB+DB PRESS plus)

知識ゼロから学ぶソフトウェアテスト 【改訂版】

知識ゼロから学ぶソフトウェアテスト 【改訂版】

テスト駆動開発入門

テスト駆動開発入門

  • 作者: ケントベック,Kent Beck,長瀬嘉秀,テクノロジックアート
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2003/09
  • メディア: 単行本
  • 購入: 45人 クリック: 1,058回
  • この商品を含むブログ (161件) を見る

実践テスト駆動開発 テストに導かれてオブジェクト指向ソフトウェアを育てる (Object Oriented SELECTION)

実践テスト駆動開発 テストに導かれてオブジェクト指向ソフトウェアを育てる (Object Oriented SELECTION)