Данная статья является следующей из серии про фреймворк для тестирования PHPUnit. Читайте так же:


Тестирование исключений.


Так как генерация исключения в коде приложения является частым явлением, рассмотрим как это дело можно тестировать с помощью PHPUnit.
В старых статьях на эту тему можно встретить использование метода setExpectedException(), но имейте ввиду, что в новых версиях phpUnit используется метод expectException() для указания типа ожидаемого исключения.

Метод expectException(), а так же директива @expectedException используются в тестах для указания "ожидать такое-то исключение". Тест считается пройденным, если возникло исключение указанного типа.

Пример.
Исключение возникает если в переданном параметре менее 4-х символов:
class User
{ 
 public function verifyPassword(array $user){
 
    if(strlen($user['password'])<4){
        throw new LengthException('Количество символов в пароле (' .$user['password']. ') не соответствует требованиям.');
    }
    //
 }
}

Тестируем:
class UserTest extends TestCase
{
    public function testVerifyPassword()
    {
        $obj = new User();
        $user['password'] = '123';
        $this->expectException(LengthException::class);
        $obj->verifyPassword($user);
    }
}

данный код можно было бы переписать так:
class UserTest extends TestCase
{ 
     /**
      * @expectedException LengthException
      */
    public function testVerifyPassword()
    {
        $obj = new User(); 
        $user['password'] = '123';
        $obj->verifyPassword($user);
    }
} 
т.е. использовать директиву @expectedException с указанием нужного исключения.


ВАЖНО! После того, как PHPUnit поймает ожидаемое исключение, выполнение данного тестирующего метода прекратится!
Другими словами - если в одном методе у вас 2 или больше тестов, например:
$this->expectException(LengthException::class);
$this->assertEquals(8, $result, 'Двойка в третьей степени');
то при выполнении первого теста с исключением, второй будет пропущен (при условии что исключение будет получено). Поэтому нужно размещать тесты исключений в разных методах или:
- в тест-методе оформлять блоки try...catch;
- использовать data provider.




Анализ покрытия кода тестами.


При большом количестве классов можно забыть протестировать какие-то методы или разные варианты возвращаемых ими результатов. Так же можно что-то отложить на потом или вообще вдруг решить тестировать то, что до этого не собирались. Как же оперативно проверить что уже было протестировано, а что нет?!! В PHPUnit для этого используется инструмент php-code-coverage.

Для использования нужно предварительно подключить php-расширение Xdebug в файле интерпретатора php - php.ini.
В OpenServer файл php.ini меняется так:
меню -> Дополнительно -> Конфиграция -> PHP
Откроется файл конфигурации, где необходимо раскомментировать строку (удалить спереди точку с запятой):
;zend_extension="e:/openserver/modules/php/PHP-5.6/ext/php_xdebug.dll"
после внесения изменений не забыть перезагрузить сервер.

Проверить подключено ли расширение, выполнить скрипт с командой:
phpinfo();
или открыть ссылку http://127.0.0.1/openserver/phpinfo.php
должен присутствовать блок «xdebug».

Выполнение:
phpunit --coverage-html tests\coverage
тут указываем, что отчет нужно предоставить в виде статичных html файлов и разместить их в папке coverage, которая появится в каталоге tests.

Открыв файл index.html из папки coverage можно увидеть список классов которые попали в отчет. При клике на названии класса открывается страница со статистикой по данному классу. Пример:


Красной строкой выделен фрагмент упущенный при создании тестов. Т.е., в данном случае, нужно написать тест при котором данный метод будт возвращать значение false.
Если при выполнении команды возникнет ошибка:
No whitelist configured, no code coverage will be generated
то нужно изменить/создать в корне проекта файл phpunit.xml и вставить туда блок <whitelist> с указанием каталога который нужно проверять:
<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true">
    <filter>
        <whitelist>
            <directory suffix=".php">app</directory>
        </whitelist>
    </filter>
</phpunit>
тут указываем, что нужно проверить покрытие кода тестами в php файлах из каталога app.

Так же используется блок <blacklist> для указания каталогов и файлов не требующих проверки.
Подробнее в документации.

При работе с Composer в командной строке, при включенном php-расширение Xdebug, может появляться сообщение:
You are running composer with xdebug enabled. This has a major impact on runtime performance. See https://getcomposer.org/xdebug
В котором сказано, что включенное расширение xdebug оказывает существенное влияние на производительность (снижает). Как решить эту проблему читайте в моей заметке.

В следующей статье я расскажу как работать с имитирующими объектами (моками), чем завершим серию статей по основам использования PHPUnit.