Codeception - модульное (unit) тестирование. Создание имитирующих объектов. Синтаксический сахар - verify/specify.
Установка и основы работы с Codeception были рассмотрены в первой статье данной серии. Сейчас остановимся на модульном(unit) тестировании.
Для модульного тестирования, как и для других типов, в фреймворке Codeception существует два способа написания тестов, которым соответствуют два типа наименования файлов: Cept и Cest. Cept строится по сценарию (функциональное программирование), а Cest на базе объектов (ООП). Кроме того, Codeception может выполнять оригинальные PHPUnit-тесты для модульного тестирования т.к. наследуется от данной библиотеки.
Создание по типу cept:где «Name» - названия файла теста.
Появится файл tests\unit\NameCept.php с содержимым:
Создание по типу cest:Появится файл tests\unit\OneCest.php с содержимым:Каждый публичный метод, не начинающийся с нижнего подчеркивания, будет выполнен как тест.
Это обычные для Codeception типы организации тестов. Для использования стандартных PHPUnit утверждений (asserts), должен быть включен модуль «Asserts» в конфигурационном файле tests\unit.suite.yml (по-умолчанию уже включен).
Доступ к утверждениям (asserts) можно получить с помощью переменной $I:
Кроме того есть возможность последним аргументом указывать текстовые сообщения, которые, во-первых, делают более читаемыми теста, а во-вторых отобразятся в консоли в случае провала указанного теста:
Тип cest может использовать события _before и _after непосредственно в тестирующем классе. Эти и другие события, для обоих типов тестов могут быть использованы в помощнике tests\_support\Helper\Unit.phpСписок событий можно посмотреть по ссылке. Правда нет полного аналога методу setUpBeforeClass(), код которого выполнялся бы перед выполнением тестов из каждого отдельного класса. Можно использовать _beforeSuite(), код которого выполнится только один раз до начала тестирования.
Создание тестов по типу phpUnit:Появится файл tests\unit\NameTest.php с содержимым:
В данном случае, создается класс, который по цепочке наследования наследуется от phpUnit и поэтому тесты можно писать в стиле этого фреймворка и используя его методы. При необходимости, можно перенести ваши готовые тесты из phpUnit целиком. Только если вы использовали доп.пакет phpunit/dbunit для работы с базой данных в тестах phpUnit, не забываем подключить данный пакет в классе теста. Для для этого достаточно подключить трейт:илив зависимости от версии phpUnit. И папку _data с xml файлом для заполнения данными тестовой таблицы нужно скопировать в папку tests\unit.
Методы _before() и _after() вызывают методы setUp() и tearDown() у phpUnit, поэтому в них так же можно писать код который выполняется перед каждым методом в тестовом классе и после каждого метода соответственно. При данном способе написания модульных тестов можно использовать все методы phpUnit, например setUpBeforeClass().
Так же как и для других типов тестов есть возможность подключать и использовать модули Codeception. Таким образом можно использовать тот же метод seeInDatabase() модуля Db для проверки наличия данных в БД (подробнее тут).
В своей статье "Основы PHPUnit - 1 часть." и я писал как создаются модульные тесты. Codeception выступает в качестве обертки для PHPUnit. Поэтому подробнее ознакомиться с модульным тестированием и посмотреть примеры можно по ссылке.
Работа с имитирующими объектами в Codeception.Для удобства использования, Codeception имеет свою обертку поверх стандартной работы с имитирующими объектами в phpUnit. Использовать ее можно во всех типах модульных тестов Codeception. А почитать про имитирующие объекты в phpUnit можно тут.
Подключаем класс Stub в нужном файле теста:
Методы создающие имитирующий объект без выполнения метода конструктора класса.- Метод make() позволяет переопределить нужное свойство или метод. Остальные свойства и методы остаются без изменений. Не забываем, что метод конструктора не будет выполнен, а значит некоторые свойства объекта могут быть не инициализированы, если это предусмотрено в конструкторе.
Переопределяем метод readAll() класса User:
- Метод makeEmpty():
- Метод makeEmptyExcept():
- Метод construct() позволяет переопределить указанные свойства и методы.
- Метод constructEmpty() создает объект класса, все методы которого возвращают null и переопределить указанные свойства/методы.
- Метод constructEmptyExcep() создает объект класса, все методы которого возвращают null кроме одного указанного метода, который будет выполнять свой оригинальный код. так же есть возможность переопределить нужные свойства/методы.
Например создадим имитирующий объект на базе класса User аналогичный оригиналу но с переопределенным методом readAll():
Вместо названия класса, в качестве первого аргумента данным методам можно указывать объект данного класса.
- Метод Stub::update позволяет переопределить свойства/методы у созданного ранее имитирующего объекта.
Еще пример – допустим создали пустой имитирующий объект у которого все методы являются заглушками (возвращают null):а далее, для какой-то проверки понадобилось переопределить метод readAll():
Так же есть методы never, once, exactly и др. для уточнения того сколько раз должен вызываться указанный метод. Например укажем что метод getName() не должен быть вызван ни разу в процессе тестирования иначе выбросить исключение:
Подробное описание этих и других методов с примерами можно посмотретьпо ссылке или в файле vendor\codeception\codeception\src\Codeception\Util\Stub.php
Синтаксический сахар Codeception.- codeception/verify;
- codeception/specify.
Глобальная установка (в каталог текущего пользователя):Для установки в текущий проект:
После установки сразу можно использовать данный синтаксис, как-то подключать не нужно.
Сравните два теста, которые описаны ниже - первый с применением стандартного синтаксиса PHPUnit, а второй — с использованием пакета verify.и
Можно сначала указывать комментарий, который будет так же выведен при ошибке:
Вместо функции verify() можно использовать синоним:с такими же аргументами.
Методы утверждений (asserts) используемые данным пакетом схожи с теми, что использует PHPUnit. В примере вместо assertEquals() используется equals(). Чаще всего достаточно просто убрать приставку «assert»:assertTrue – true;assertFalse – false;assertNotNull – notNull;
но есть и такие:assertEmpty - isEmpty
Посмотреть соответствие методов можно в файле vendor\codeception\verify\src\Codeception\Verify.php .Еще примеры.
codeception/specifyПакет позволяет писать несколько тестов PHPUnit в одном методе разбивая их на блоки. Код внутри specify блоков изолирован. Любое изменение свойств объектов и переменных не будет отражено в других блоках кода.Так же можно указать комментарий к каждому блоку теста.
Установка:для установки каталог vendor текущего проекта:
После установки нужно подключить трейт в классе теста:
При этом я заметил конфликт данного пакета с расширением для PHPUnit используемом для работы с БД - DBUnit. В данном случае возникает ошибка: [PHPUnit_Framework_Exception] ReflectionProperty::setValue(): Cannot assign to an array of nodes (duplicate subnodes or attr detected)