Search code examples
phpphpunitcode-coverage

How to cover Exception Classes in PHPUnit


Im aiming for very high code coverage and want to either cover exception classes or have them excluded from the codecoverage reports.

Example code

class My_DataException extends Exception
{}

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

How can I either get code coverage on My_DataException (in library/My/DataException.php) or have the file excluded from appearing in the code coverage report? I'd prefer not to use the annotation method (@codeCoverageIgnore or something like that).

My phpunit.xml has a black list defined, and no whitelist

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

Every Exception file will end in "Exception.php" so im not sure why the suffix portion doesnt work.

Additional Details:

  • This is not a question about the right amount of coverage
  • I would prefer to not use the annotation method in each Exception file
  • Every Exception file will end in "Exception.php" eg. My/Exception.php or My/DataException.php

Solution

  • For the following code:

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

    You will get code coverage if you execute that line in tests:

    new Foo;
    

    For such a test you can tell Phpunit which exception you expect with an annotation:

    /**
     * @expectedException My_DataException
     */
    

    However Exceptions are normally exceptions so you do not cover them but there can be in there for safety reasons too and you yet do not know how you can trigger them with test-setup / data / parameters.

    Then think harder and try to trigger them. Otherwise it might be that the code is superfluous because technically you are not able to throw the exception, hence it is not necessary.

    For the cases you know they can happen but you still can not trigger them (is that possible?) you can mark certain areas of your script to be excluded from coverage reporting in the source code:

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

    Use it sparsely you might want to remove this in the future.