Как покрыть классы исключений в PHPUnit

Я стремлюсь к очень высокому покрытию кода и хочу либо охватить классы исключений, либо исключить их из отчетов о покрытии кода.

Пример кода

class My_DataException extends Exception
{}

class Foo
{
   function __construct() { throw new My_DataException('see?'); }
}

Как я могу либо получить покрытие кода для My_DataException (в библиотеке/My/DataException.php), либо исключить файл из отчета о покрытии кода? Я бы предпочел не использовать метод аннотации (@codeCoverageIgnore или что-то в этом роде).

В моем phpunit.xml определен черный список, а белый список отсутствует.

<filter>
    <blacklist>
        <directory suffix="Exception.php">../library/</directory>
    </blacklist>
</filter>

Каждый файл исключения заканчивается на «Exception.php», поэтому я не уверен, почему часть суффикса не работает.

Дополнительные детали:

  • Это не вопрос правильного количества покрытия
  • Я бы предпочел не использовать метод аннотаций в каждом файле исключений.
  • Каждый файл исключения будет заканчиваться на «Exception.php», например. My/Exception.php или My/DataException.php

person Mike Graf    schedule 09.08.2012    source источник
comment
Какие версии (php, xdebug, phpunit, php-codeCoverage) вы используете? Для меня исключения без исполняемого кода не отображаются в отчете о покрытии. См.: dl.dropbox.com/u/ 3615626/stackoverflow/ Запуск phpunit --coverage-text (или html) показывает мне только один файл, а не исключение.   -  person edorian    schedule 10.08.2012
comment
PHPUnit 3.6.10. PHP 5.3.10-1ubuntu3.2, Xdebug v 2.1.3. Не уверен насчет php-codeCoverage... н/д?   -  person Mike Graf    schedule 31.08.2012


Ответы (2)


Для следующего кода:

class Foo
{
    function __construct() {
        throw new My_DataException('see?');
    }
}s

Вы получите покрытие кода, если выполните эту строку в тестах:

new Foo;

Для такого теста вы можете сообщить Phpunit, какое исключение вы ожидаете, с помощью аннотации:

/**
 * @expectedException My_DataException
 */

Однако исключения, как правило, являются исключениями, поэтому вы их не охватываете, но они могут быть и там по соображениям безопасности, и вы еще не знаете, как вы можете вызвать их с помощью test-setup/data/parameters.

Тогда подумайте лучше и попытайтесь вызвать их. В противном случае может оказаться, что код лишний, потому что технически вы не можете генерировать исключение, следовательно, в нем нет необходимости.

Для случаев, когда вы знаете, что они могут произойти, но вы все равно не можете их вызвать (возможно ли это?), вы можете пометить определенные области вашего скрипта, чтобы исключить их из отчетов о покрытии в исходном коде:

// @codeCoverageIgnoreStart
throw new My_DataException('see?');
// @codeCoverageIgnoreEnd

Используйте его редко, возможно, вы захотите удалить его в будущем.

person hakre    schedule 10.08.2012
comment
Ваши комментарии о покрытии исключений другими классами заставили меня задуматься. Я всегда стараюсь делать @ покрывает Fooclass::method, поэтому я никогда не получаю покрытие по классам исключений. Я мог бы удалить аннотации @covers, чтобы получить охват классов исключений в тестах, которые их выдают. - person Mike Graf; 31.08.2012

Я искал способ охватить фактические файлы исключений, вот как я в конце концов наткнулся на ответ:

<?php

/**
 * Simple test for exception
 */
class Api_ExceptionTest extends PHPUnit_Framework_TestCase
{
    /**
     * Test can construct the exception, then throw it.
     *
     * @expectedException Api_Exception
     */
    public function testThrowException()
    {
        $exception = new Api_Exception();
        throw $exception;
    }
}   
person Mike Graf    schedule 21.09.2012