簡體   English   中英

PHPUnit達到100%的代碼覆蓋率

[英]Reaching 100% Code Coverage with PHPUnit

我一直在為一個項目創建測試套件,盡管我意識到獲得100%的覆蓋率並不是一個人應該努力指標,但是我希望代碼覆蓋率報告中有些奇怪的地方澄清。

看截圖:

在此處輸入圖片說明

因為要測試的方法的最后一行是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語句也是如此。 因此,這種行為至少在某種程度上是一致的,但仍然令我感到困惑。

編輯2:

我正在運行:OS X上的PHPUnit 3.6.7,PHP 5.4.0RC5,XDebug 2.2.0-dev

第一關:100%的代碼覆蓋率是一個重要指標, 爭取 付出同樣的努力並不總是可以實現的,而且這樣做並不總是很重要的。

問題來自xDebug告訴PHPUnit此行是可執行的,但未涵蓋。

在簡單的情況下,xDebug可以告訴您該行不可達,因此您可以獲得100%的代碼覆蓋率。

請參閱下面的簡單示例


第二次更新

現在已解決了xDebug bugtracker的問題,因此構建新版本的xDebug將解決這些問題:)

更新(有關PHP 5.3.x的問題,請參見下文)

由於您正在運行PHP 5.4和xDebug的DEV版本,因此我已經安裝了它們並對其進行了測試。 我遇到了與您相同的問題,但您評論了相同的輸出。

我不確定這個問題是否來自xDebug的php-code-coverage (phpunit模塊)。 xDebug開發人員也可能會遇到問題。

我已經用php-code-coverage提交了一個錯誤,我們將找出問題的根源。


對於PHP 5.3.x問題:

對於更復雜的情況下,這可能會失敗。

對於您顯示的代碼,我只能說“它對我有用”( 下面的復雜示例 )。

也許更新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)

這里的大部分問題是堅持要獲得“行”的100%執行覆蓋率。 (經理喜歡這個想法;這是他們可以理解的簡單模型)。 許多行不是“可執行的”(空格,函數聲明,注釋,聲明之間的間隙,“純語法”,例如,開關或類聲明的結束“}”,或跨多個源代碼行的復雜語句)。

您真正想知道的是,“是否覆蓋了所有可執行代碼?” 這種區別似乎很愚蠢,但卻導致了解決方案。 XDebug很好地按行號跟蹤執行的內容,因此基於XDebug的方案將報告已執行行的范圍。 您會在此線程中遇到麻煩,包括笨拙的解決方案:必須在代碼中加上“不要算我”注釋,將“}”與最后一個可執行語句放在同一行,等等。願意這樣做,更不用說維護它了。

如果將可執行代碼定義為可以被條件代碼調用或由條件代碼控制的代碼(編譯器人員稱為“基本塊”),並且以這種方式進行覆蓋率跟蹤,則代碼的布局和無聊的情況簡直消失了。 這種類型的測試覆蓋率工具會收集所謂的“分支覆蓋率”,通過執行所有可執行代碼,您實際上可以獲取100%的“分支覆蓋率”。 此外,它還會處理一些有趣的情況,其中您在一行中有條件(使用“ x?y:z”),或者您在一行中有兩個常規語句(例如,

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

由於XDebug是按行跟蹤的,因此我相信它將這視為一條陳述,並在控制到達該行時將其視為覆蓋范圍,而實際上有5個部分需要實際測試。

我們的PHP測試覆蓋率工具實現了這些想法。 特別是,它了解return語句后的代碼不可執行,並且會告訴您尚未執行,如果它不是非空的。 這使得OP的原始問題消失了。 沒有更多的玩游戲來獲得“真實”的覆蓋率。

與所有選擇一樣,有時也有不利之處。 我們的工具具有僅在Windows下運行的代碼工具組件。 檢測的PHP代碼可以在任何地方運行,並且處理/顯示由獨立於平台的Java程序完成。 因此,這對於OP的OSX系統可能很尷尬。 該工具可以在支持NFS的文件系統上正常工作,因此可以說可以在PC上運行該工具並對其OSX文件進行檢測。

有人試圖提高自己的承保范圍數而引起了這個特殊的問題。 問題是恕我直言,是人為的,可以通過逐步解決問題來解決。 還有另一種無需編寫更多測試即可增加數量的方法,那就是查找並刪除重復的代碼。 如果刪除重復的副本,則可以更少的代碼來測試和測試一個(非)副本,從而效果測試(現在不存在的另一個副本),因此更容易獲得更大的數字。 您可以在此處了解更多信息。

關於您的switch語句代碼覆蓋率問題,只需添加一個“默認”情況而不執行任何操作,您將獲得完整的覆蓋率。

這是使switch語句100%覆蓋的方法:

確保至少有一個測試發送不存在的案例。

因此,如果您有:

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

確保你的測試中的至少一個發送名稱既不是terry還是lucky ,也不gerard

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM