Codeception - модульное (unit) тестирование. Создание имитирующих объектов. Синтаксический сахар - verify/specify.

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.
codeception/verify

Глобальная установка (в каталог текущего пользователя):Для установки в текущий проект:

После установки сразу можно использовать данный синтаксис, как-то подключать не нужно.

Сравните два теста, которые описаны ниже - первый с применением стандартного синтаксиса 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)

📎📎📎📎📎📎📎📎📎📎