
По умолчанию модуль будет пытаться заполнить базу данными из дампа, и очистить ее после выполнения каждого теста. А если точнее, он перезапишет данные в БД из подготовленного для этого дампа. Используется дамп данных в SQL формате.
В настоящее время документация фреймворка для тестирования Codeception немного отстала от разработки самого проекта, поэтому в статье возможны неточности.
Модуль Db работает с любыми базами данных пооддерживающими PDO. Он может быть использован с любыми тестами, если они не являются довольно медленными. Загрузка дампа может занять продолжительное время, поэтому для данной цели могут быть использованы и другие подходы.
Для использования модуля Db нужно:
- создать тестовую БД (в примере конфигурации это test.loc);
- заполнить ее данными необходимыми для тестов (если нужно) вручную или используя фикстуры;
- создать дамп этой базы и поместите его в папку tests/_data (в примере это dump.sql);
- добавить модуль с нужными параметрами в конфигурационный файл.
Т.к. соединение модуля с базой данных может понадобиться для разных типов тестов, можно указать настройки соединения в основном конфигурационном файле codeception.yml:
modules: config: Db: dsn: 'mysql:host=localhost;dbname=test' user: 'root' password: ''а подключить сам модуль Db с указанием более специфичных настроек в конфигурационном файле соответствующего типа тестов, например в tests/acceptance.suite.yml (будем создавать приемочные тесты):
modules: enabled: - PhpBrowser: url: http://test.loc - \Helper\Acceptance - Db: dump: 'tests/_data/test.sql' populate: true cleanup: true reconnect: trueтут:
- populate - следует ли загружать дамп перед запуском набора тестов
- cleanup – восстанавливать ли БД из дампа перед каждым тестом
- reconnect - должен ли модуль повторно подключаться к базе данных перед каждым тестированием
Еще примеры настройки и использования данного модуля можно посмотреть в файле vendor\codeception\codeception\docs\modules\Db.md
Пример использования.
Создадим тест который будет проверять сохранение данных из формы заполненной пользователем в базу данных.
Допустим форма имеет такой вид:
<div class="user-form"> <form action="" method="POST"> <input type="name" name="name"> <input type="email" name="email"> <input type="hidden" name="form" value='true'> <input type="submit"> </form> </div>При успехе пользователю выводится сообщение на странице 'Данные сохранены.'
Для теста нам потребуется дамп базы данных которая должна называться "test" (так мы указали в файле конфигурации) и содержать пустую таблицу "users" с такой структурой:

Создаем дамп базы (в phpmyadmin это закладка "Экспорт") и сохраняем в tests/_data.
Теперь создаем файл теста:
codecept generate:cest acceptance UserFormCest
Открываем его в папке tests\acceptance и заполняем:
<?php class UserFormCest { public function _before(AcceptanceTester $I) { } public function _after(AcceptanceTester $I) { } public function formFillSave(AcceptanceTester $I) { $I->wantTo('Заполняю данные пользователя в форму и сохраняю в БД'); $I->amOnPage('/'); $I->fillField('name','Иванов'); $I->fillField('email','ivanov@gmail.com'); $I->click('.user-form input[type=submit]'); $I->see('Данные сохранены.'); $I->seeInDatabase('users', [ 'name' => 'Иванов', 'email' => 'ivanov@gmail.com', ]); } }
Перед выполнением каждого тестового метода у нас будет загружаться дамп базы данных который мы указали в настройках:
dump: 'tests/_data/test.sql'т.к. мы указали директиву cleanup при конфигурировании модуля. Таким образом, если бы в примере было несколько тестирующих методов, то все они имели бы одинаковую БД для старта.
В тесте мы указываем, что находимся на главной странице, далее заполняем 2 поля формы с атрибутом «name» - name и email. Кликаем по кнопке отправки и осуществляем 2 проверки того, что данные действительно были сохранены в базу данных:
$I->see('Данные сохранены.');тут используем сообщение которое должно отобразиться пользователю при успешном сохранении данных и
$I->seeInDatabase()данный метод непосредственно использует обращение к базе данных к таблице users для поиска строки с указанными данными.
Запустить тестирование можно обычным способом:
codecept run acceptance
Методы модуля Db.
Есть ряд методов которые можно использовать для тестирования при использовании модуля Db:`seeInDatabase`,` dontSeeInDatabase`, `seeNumRecords`,` grabFromDatabase` и `grabNumRecords`
они принимают массивы в качестве критериев выборки. Условие WHERE генерируется с использованием ключа элемента в качестве имени поля и значение позиции в качестве значения поля.
Пример:
$I->seeInDatabase ('users', array ('name' => 'Davert', 'email' => 'davert@mail.com'));будет генерировать:
SELECT COUNT (*) FROM `users` WHERE` name` = 'Davert' AND `email` = 'davert@mail.com'
Метод grabColumnFromDatabase() выбирает все значения из столбца в базе данных. Нужно указать имя таблицы, нужный столбец и критерии:
$mails = $I->grabColumnFromDatabase ('users', 'email', array ('name' => 'RebOOter'));Метод haveInDatabase() добавляет запись в БД:
$I->haveInDatabase('users', array('name' => 'miles', 'email' => 'miles@davis.com'));Метод updateInDatabase() обновляет запись в базе данных:
$I->updateInDatabase ('users', array ('isAdmin' => true), array ('email' => 'miles@davis.com'));Примеры использования методов см. в файле vendor\codeception\codeception\docs\modules\Db.md
Модуль Db содержит несколько публичных свойств, которые могут понадобиться для создания соединения с базой данных в своих тестах:
- dbh (содержит соединение PDO);
- driver (содержит драйвер подключения)
Получить доступ к этим свойствам можно из помошников, а уже к свойствам и методам помошников есть доступ непосредственно в тесте.
Для ускорение выполнения тестов взаимодействующих с БД рекомендуется использование базы данных SQLite.
Фикстуры.
По фикстурам в Codeception (без использования интеграции с фреймворками) пока обновленной информации совсем мало. Та, что есть в официальной документации, устарела. Поэтому опишу свое видение и в будущем, возможно, откорректирую.
Для хранения фикстур используется класс Fixtures который представляет из себя хранилище данных. Сначала мы сохраняем туда нужные данные (массивы фикстур), а далее можем получить в любом нужном классе. Для удобства создан статический интерфейс методов класса Fixtures, т.е. не нужно получать объект.
Методы класса Fixtures можно посмотреть в файле vendor\codeception\codeception\src\Codeception\Util\Fixtures.php
Основные:
Fixtures::add('users', ['name' => 'Ivan']); //сохраняем Fixtures::exists('users'); //проверяем наличие в хранилище Fixtures::get('users'); //получаем
Согласно текущей документации, фикстуры должны быть заданы в bootstrap файле, т.е. единожды и до начала тестирования.
Перед использованием фикстур нужно создать тестовую базу данных. Это делается вручную или используя модуль Db (перезагрузкой дампа).
Обычно создается чистая тестовая база данных со структурой нужных таблиц, заполнение которых уже происходит с помощью фикстур.
Вы можете использовать в классах Cest метод _before() для загрузки фикстур перед началом теста (каждого метода). Метод _after позволяет очистить БД между выполнением тестирующих методов одного класса. Удалять внесенные тестами данные после выполнения каждого теста можно и с помощью модуля Db, если в настройках модуля указать дамп и параметр cleanup: true
dump: 'tests/_data/test.sql' cleanup: true
Если быть точным, то данный механиз просто перезапишет базу данных из дампа. И так перед каждым тесто, что занимает сравнительно много времени. Поэтому в моем примере я не буду это использовать.
Но подключить модуль Db для соединения с базой данных нужно в любом случае. Например так в файле tests\acceptance.suite.yml:
modules: enabled: - Db: dsn: 'mysql:host=localhost;dbname=test' user: 'root' password: ''
В качестве примера создам приемочный тест, работающий с все той же таблицей users.
Для хранения фикстур создаем папку _fixtures в каталоге test. В ней создаем файл фикстур users.php который будет содержать данные для добавления в таблицу users:
<?php return [ [ 'name' => 'testName1', 'email' => 'testName1@gmail.com', ], [ 'name' => 'testName2', 'email' => 'testName2@gmail.com', ] ];
Для удобства воспользуемся файлом предзагрузки tests\_bootstrap.php, создаем если его нет. Определяем константу которая будет содержать путь к папке с фикстурами:
<?php define("FIXTURES_DIR", __DIR__ . '/_fixtures/');Данная константа может понадобиться для различных типов тестов.
Теперь создаем, файл предзагрузки для приемочных тестов _bootstrap.php в папке tests\acceptance с содержимым:
<?php use Codeception\Util\Fixtures; /* * Используем класс Fixtures для хранения фикстур * FIXTURES_DIR - константа заданная в главном файле _bootstrap */ Fixtures::add('users', require(FIXTURES_DIR . 'users.php'));Данный код можно указать и в основном файле предзагрузки, созданном выше, если вы планируете использовать указанные фикстуры и для других типов тестов (функциональных и модульных).
Теперь до начала тестирования у нас будет подключен файл фикстур и сохранен в глобальное хранилище фикстур которое предоставляет класс Fixtures.
Создаем приемочный тест для демонстрации работы с фикстурами:
codecept generate:cest acceptance UserInDb
Добавляем содержимое:
<?php use Codeception\Util\Fixtures; class UserInDbCest { public function _before(AcceptanceTester $I) { if(Fixtures::exists('users')){ /* * Добавляем строки в таблицу 'users' */ foreach (Fixtures::get('users') as $item) { $I->haveInDatabase('users', $item); } } } public function _after(AcceptanceTester $I) { } public function checkUserInDb(AcceptanceTester $I) { $I->wantTo('Проверяем наличие данных в таблице users'); $I->seeInDatabase ('users', array ('name' => 'testName1', 'email' => 'testName1@gmail.com')); } }
После запуска этого теста:
codecept run acceptance UserInDbCestдолжны получить уведомление об успешном его прохождении. Значит фикстуры отработали.
В данном примере я использовал метод _before() для заполнения таблицы фикстурами (нужными для тестирования данными). Напомню, что данный метод выполняется автоматически перед каждым тестовым методом.
Строкой
if(Fixtures::exists('users'))проверяем наличие нужной фикстуры в хранилище по ее ключу. Получаем данные с помощью
Fixtures::get('users')и далее добавляем массив данных в БД используя метод haveInDatabase():
$I->haveInDatabase('users', $item);
Т.к. массив содержит вложенные массивы каждый из которых представляет собой отдельный набор для добавления в таблицу (отдельная строка) используется цикл.
Видно, что я не использовал метод _after() для очистки таблицы между тестами. Это не потребовалось т.к. я использовал метод haveInDatabase() для заполнения данными, а данный метод автоматически удаляет внесенные данные сразу после теста.
Быстрая очистка таблицы.
Использование способа очистки таблицы перезаписью дампа база данных довольно долгий способ. Можно воспользоваться методом load() класса Codeception\Lib\Driver\Db который позволяет выполнить произвольный запрос к БД.В файле нужного помощника (tests\_support\Helper):
public function clearTable($table){ $db = $this->getModule('Db')->driver; $db->load(["TRUNCATE TABLE `$table`"]); }
В нужном тесте:
$I->clearTable('название таблицы');эту строку можно разместить как только в нужном методе так и в методах _before() или _after().
Данная статья является одной из серии статей про фреймворк для тестирования Codeception. Читайте так же:
- Установка, настройка и базовое использование фреймворка для тестирования "Codeception".
- Codeception - приемочные тесты. Использование Selenium.
- Codeception - модульное (unit) тестирование. Создание имитирующих объектов.