web-dev-qa-db-ja.com

PHPUnitで100%のコードカバレッジに到達

私はプロジェクトのテストスイートを作成している最中ですが、100%のカバレッジを取得することは、メトリックではないことに気づきました。に、コードカバレッジレポートに奇妙な部分がありますが、それについて説明したいと思います。

スクリーンショットを参照してください:

enter image description here

テストされているメソッドの最後の行はreturnであるため、最後の行(単なる閉じ括弧)は実行されていないものとして表示され、その結果、メソッド全体が実行されていないというフラグが立てられます。概要。 (または、レポートを正しく読んでいません。)

完全な方法:

static public function &getDomain($domain = null) {
    $domain = $domain ?: self::domain();

    if (! array_key_exists($domain, self::$domains)) {
        self::$domains[$domain] = new Config();
    }

    return self::$domains[$domain];
}

これには理由がありますか、それともグリッチですか?

(はい、読み通しました PHPUnitで100%のコードカバレッジを取得する方法 、似ていますが異なるケースです。)

編集:

レポートを調べてみると、コードの他の場所にあるswitchステートメントにも同じことが当てはまることがわかりました。したがって、この動作は少なくともある程度一貫していますが、それでも私には困惑します。

Edit2:

私が実行しているのは:PHPUnit 3.6.7、PHP 5.4.0RC5、XDebug 2.2.0-OSX上のdev

35
nikc.org

まず最初に:100%のコードカバレッジは、striveの優れた指標です。かなりの努力で常に達成できるとは限らず、そうすることが常に重要であるとは限りません:)

この問題は、この行は実行可能であるがカバーされていないことをPHPUnitに通知するxDebugに起因します。

単純なケースでは、xDebugはその行に到達できないことを通知できるため、100%のコードカバレッジが得られます。

以下の簡単な例を参照してください。


2回目の更新

この問題は修正されました xDebug bugtracker したがって、xDebugの新しいバージョンをビルドするとこれらの問題が解決されます:)

更新(php 5.3.xの問題については以下を参照)

PHP 5.4とxDebugのDEVバージョンを実行しているので、それらをインストールしてテストしました。コメントしたのと同じ出力で、同じ問題が発生します。

問題がxDebugのphp-code-coverage(phpunitモジュール)に起因するかどうかは100%わかりません。 xDebugdevの問題でもある可能性があります。

php-code-coverage でバグを報告しました。問題の原因を特定します。


PHP 5.3.xの問題の場合:

より複雑なケースでは、これ[〜#〜] can [〜#〜]は失敗します。

あなたが示したコードについて、私が言えるのは「それは私のために働く」ということだけです(以下の複雑なサンプル)。

XDebugとPHPUnitのバージョンを更新して、再試行してください。

現在のバージョンでは失敗するのを見てきましたが、クラス全体がどのように見えるかによって異なります。

?:演算子やその他の単一行のマルチステートメントを削除することも役立つ場合があります。

私の知る限り、これらのケースの多くを回避するために、xDebugには継続的なリファクタリングがあります。 xDebugはかつて「ステートメントカバレッジ」を提供できるようにしたいと考えていましたが、それで多くのケースが修正されるはずです。今のところ、ここでできることはあまりありません

//@codeCoverageIgnoreStart//@codeCoverageIgnoreEndはこの行を「カバー」しますが、それは本当に醜く見え、通常は良いよりも悪いことをしています。

これが発生する別のケースについては、以下の質問と回答を参照してください。

what-to-do-when-project-coding-standards-conflicts-with-unit-test-code-coverage


簡単な例:

<?php
class FooTest extends PHPUnit_Framework_TestCase {
    public function testBar() {
        $x = new Foo();
        $this->assertSame(1, $x->bar());
    }
}

<?php
class Foo {
    public function bar() {
        return 1;
    }
}

生成:

phpunit --coverage-text mep.php 
PHPUnit 3.6.7 by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 3.50Mb

OK (1 test, 1 assertion)

Generating textual code coverage report, this may take a moment.

Code Coverage Report 
  2012-01-10 15:54:56

 Summary: 
  Classes: 100.00% (2/2)
  Methods: 100.00% (1/1)
  Lines:   100.00% (1/1)

Foo
  Methods: 100.00% ( 1/ 1)   Lines: 100.00% (  1/  1)

複雑な例:

<?php

require __DIR__ . '/foo.php';

class FooTest extends PHPUnit_Framework_TestCase {

    public function testBar() {
        $this->assertSame('b', Foo::getDomain('a'));
        $this->assertInstanceOf('Config', Foo::getDomain('foo'));
    }
}

<?php

class Foo {
    static $domains = array('a' => 'b');

    static public function &getDomain($domain = null) {
        $domain = $domain ?: self::domain();
        if (! array_key_exists($domain, self::$domains)) {
            self::$domains[$domain] = new Config();
        }
        return self::$domains[$domain];
    }
}

class Config {}

生成:

PHPUnit 3.6.7 by Sebastian Bergmann.

.

Time: 0 seconds, Memory: 3.50Mb

OK (1 test, 2 assertions)

Generating textual code coverage report, this may take a moment.

Code Coverage Report 
  2012-01-10 15:55:55

 Summary: 
  Classes: 100.00% (2/2)
  Methods: 100.00% (1/1)
  Lines:   100.00% (5/5)

Foo
  Methods: 100.00% ( 1/ 1)   Lines: 100.00% (  5/  5)
36
edorian

ここでの問題の多くは、「ライン」の100%の実行カバレッジを取得することへの主張です。 (マネージャーはこのアイデアが好きです。それは彼らが理解できる単純なモデルです)。多くの行は「実行可能」ではありません(空白、関数宣言間のギャップ、コメント、宣言、「純粋な構文」(スイッチまたはクラス宣言の終了「}」、複数のソース行に分割された複雑なステートメントなど)。

あなたが本当に知りたいのは、「すべての実行可能コードはカバーされていますか?」です。この区別はばかげているように見えますが、解決策につながります。 XDebugは、実行される内容を行番号で追跡するため、XDebugベースのスキームは実行された行の範囲を報告します。そして、このスレッドで説明されている問題が発生します。たとえば、コードに「カウントしないでください」というコメントを付けたり、最後の実行可能ステートメントと同じ行に「}」を付けたりするという厄介な解決策があります。それを維持することは言うまでもなく、それを喜んで行います。

実行可能コードを、条件付き(コンパイラーが「基本ブロック」と呼ぶもの)で呼び出すことができる、または制御するコードとして定義し、カバレッジトラッキングがそのように行われる場合、コードのレイアウトとばかげたケース単に消えます。このタイプのテストカバレッジツールは、いわゆる「ブランチカバレッジ」を収集し、すべての実行可能コードを実行することで、文字通り100%の「ブランチカバレッジ」を取得することも取得しないこともできます。さらに、行内に条件文がある場合( "x?y:z"を使用)、または行内に2つの従来のステートメントがある場合(例:

 if  (...)  {   if  (...)  stmt1; else stmt2; stmt3 }

XDebugは行ごとに追跡するため、これを1つのステートメントとして扱い、実際にテストする5つの部分がある場合でも、制御が行に到達した場合はカバレッジと見なします。

私たちの PHPテストカバレッジツール はこれらのアイデアを実装しています。特に、returnステートメントに続くコードは実行可能ではないことを理解し、空でない場合は実行していないことを通知します。これにより、OPの元の問題はなくなります。 「実際の」カバレッジ数を取得するためにゲームをプレイする必要はもうありません。

すべての選択肢と同様に、マイナス面がある場合もあります。私たちのツールには、Windowsでのみ実行されるコードインストルメントコンポーネントがあります。インストルメント化PHPコードはどこでも実行でき、処理/表示はプラットフォームに依存しないJavaプログラムによって実行されます。したがって、これはOPのOSXシステムにとって厄介かもしれません。インストルメンテーション担当者NFS対応のファイルシステム全体で正常に動作するため、彼は間違いなくPCでインストルメンテーションを実行し、OSXファイルをインストルメントすることができます。

この特定の問題は、カバレッジ数を押し上げようとしている誰かによって引き起こされました。問題は私見人工であり、人工を回避することで解決できます。テストを追加せずに数値をプッシュアップする別の方法があります。それは、重複するコードを見つけて削除することです。重複を削除すると、テストするコードが少なくなり、エフェクトテスト(現在は存在しない他のコピー)で1つの(非)コピーをテストするため、より多くの数を取得しやすくなります。あなたはできる これについてもっと読むここで。

4
Ira Baxter

Switchステートメントのコードカバレッジの問題に関しては、何もしない「デフォルト」のケースを追加するだけで、完全なカバレッジが得られます。

1
Lloyd Watkin

Switchステートメントを100%カバレッジにするために行うことは次のとおりです。

存在しないケースを送信するテストが少なくとも1つあることを確認してください。

だから、あなたが持っているなら:

switch ($name) {
    case 'terry':
        return 'blah';
    case 'lucky':
        return 'blahblah';
    case 'gerard':
        return 'blahblah';
}

テストの少なくとも1つが、terryでもluckyでもgerardでもない名前を送信していることを確認してください。

0
Ibrahim Lawal