Тестирование проекта с Codeception
Введение
Важный этап при разработке приложения - это тестирование его работоспособности. Заниматься этим вручную хлопотно (особенно после каждого изменения прогонять все тесты заново) да и можно что-то пропустить. Поэтому нужен инструмент для автоматического тестирования. Как вариант - это unit-тесты. Они хороши для тестирования отдельных элементов скрипта. Но чтобы проверить функциональность всего приложения вцелом, взаимосвязь всех компонентов и модулей, нужен более серьезный инструмент. Такими возможностями обладает Codeception. Поэтому именно о нем пойдет речь в сегодняшней статье.
Codeception - это фреймворк для тестирования на основе PHPUnit и Mink. Имеет три вида тестов: модульные (unit), функциональные (functional) и приемочные (acceptance). В комплекте есть модули для тестирования различных фреймворков и API (поддерживает стандарты REST и SOAP). Также может формировать HTML и XML отчёты о тестировании.
Установить Codeception можно через Composer, Git или скачав phar-архив.
Установка через Composer
Создаем файл composer.json:
{
"name": "project name",
"require": {
"codeception/codeception": "*"
}
}
Сохраняем файл и выполняем команду composer install. После загрузки инизиализируем Codeception командой:
$ ./vendor/bin/codecept bootstrap
Установка через Git
Клонируем репозиторий с GitHub и установливаем зависимости:
$ git clone git://github.com/Codeception/Codeception.git
$ cd Codeception
$ curl -s http://getcomposer.org/installer | php
$ php composer.phar install
Инизиализируем Codeception с указанием пути к каталогу проекта:
$ php codecept bootstrap /path_to_project
Установка codecept.phar
Скачиваем phar-архив:
$ wget http://codeception.com/codecept.phar
Инициализируем командой:
$ php codecept.phar bootstrap
Модульные тесты
Сначала для удобства установим расширение Verify. Которое сделает код наших тестов более читаемым. Используем для этого Composer:
$ composer require "codeception/verify:*"
После добавления создаем базовые классы тестов:
$ ./vendor/bin/codecept build
Здесь стоит заметить что у Codeception есть команда для генерации тестов. Давайте ей воспользуемся - создадим файл для тестирования модели продукта:
$ ./vendor/bin/codecept generate:phpunit unit Product
Теперь у нас есть файл tests/unit/ProductTest.php с которым мы можем работать как PHPUnit тестом. Например:
class ProductTest extends \PHPUnit_Framework_TestCase
{
protected $product;
protected function setUp()
{
$this->product = new Product();
}
protected function tearDown()
{
$this->product = null;
}
/**
* Проверка на обязательные поля.
*/
public function testRequiredFields()
{
$this->product->name = '';
$this->product->price = '';
verify($this->product->save())->false();
$this->product->name = 'имя продукта';
$this->product->price = 5000;
verify($this->product->save())->true();
}
/**
* Проверка на получение категории.
*/
public function testGetCategory()
{
$category = $this->product->getCategory();
verify($category)->isInstanceOf('Category');
verify($category->id)->equals(1);
}
}
Запускаем модульные тесты командой:
$ ./vendor/bin/codecept run unit
При успешном выполнении увидим такой результат:
Unit Tests (2) ------------------------------------
✔ ProductTest: Required fields (0.05s)
✔ ProductTest: Get category (0.02s)
---------------------------------------------------
Time: 934 ms, Memory: 11.50MB
OK (2 tests, 4 assertions)
Функциональные тесты
У Codeception нет базового модуля для функционального тестирования. Поэтому в конфигурации необходимо включить один из поддерживаемых модулей фреймворков. Нужно это для того, что бы при запуске тестов не использовать веб сервер.
С полным списком модулей можно ознакомится на GitHub или официальном сайте. Если в списке нет подходящего модуля можно интегрировать свой фреймворк. Делается это созданием моста между BrowserKit (его использует Codeception) и нашим приложением.
Мы будем использовать собственный модуль Gateway. Этот модуль подойдет если наш фреймворк использует Symfony HttpKernel.
Сначала создаем сам модуль по адресу tests/modules/Gateway.php:
namespace Codeception\Module;
use Codeception\TestCase;
use Symfony\Component\HttpKernel\Client;
class Gateway extends \Codeception\Lib\Framework
{
public function _initialize()
{
require dirname(dirname(__DIR__)) . '/vendor/autoload.php';
$config = require dirname(__DIR__) . '/config/main.php';
$this->kernel = new \app\framework\Frontend($config);
}
public function _before(TestCase $test)
{
$this->client = new Client($this->kernel);
$this->client->followRedirects(true);
}
public function isStatusCode($code)
{
return $this->kernel->handle()->getStatusCode() === $code;
}
}
Затем подключаем его в файле конфигурации (tests/functional.suite.yml):
class_name: FunctionalTester
modules:
enabled: [Gateway, \Helper\Functional]
Пересоздаем базовые классы тестов:
$ ./vendor/bin/codecept build
Теперь можем приступать к написанию тестов.
С помощью генератора добавим тест для страницы авторизации:
$ ./vendor/bin/codecept generate:cept functional AuthPage
В созданном файле (tests/functional/AuthPageCept.php) пишем следующий код:
$I = new FunctionalTester($scenario);
$I->amOnPage('/');
$I->click('Авторизация');
$I->fillField('username','Admin');
$I->fillField('password','1q2w3e');
$I->click('Войти');
$I->see('Добро пожаловать, Admin', 'h1');
Запускаем функциональные тесты командой:
$ ./vendor/bin/codecept run functional
При успешном выполнении увидим такой результат:
Functional Tests (1) ------------------------------
✔ AuthPageCept: (0.03s)
---------------------------------------------------
Time: 165 ms, Memory: 14.25MB
OK (1 test, 1 assertion)
Приемочные тесты
Приемочные тесты расчитаны на то, что их создавать и выполнять может не только программист. А, например, тестировщик, менеджер или даже заказчик. Основное требование - это наличие браузера. И доступность приложения по указанному в конфигурации адресу.
Можно использовать как PHP-браузер, так и обычный браузер через Selenium. Мы остановимся на PHP-браузере. Указываем об этом в файле tests/acceptance.suite.yml:
class_name: AcceptanceTester
modules:
enabled: [PhpBrowser, \Helper\Acceptance]
config:
PhpBrowser:
url: 'http://localhost:8000'
Пересоздаем базовые классы тестов:
$ ./vendor/bin/codecept build
Этот модуль требует доступности приложения по адресу http://localhost:8000. Если это условие соблюдено можем приступать к тестам.
Структура и стиль написания идентичны функциональным тестам. Поэтому за пример возмем тот же тест страницы авторизации, который использовали при функциональном тестировании.
Последовательность действий такая же. Сначала генерируем тест:
$ ./vendor/bin/codecept generate:cept acceptance AuthPage
Потом заполняем его (это файл tests/acceptance/AuthPageCept.php):
$I = new AcceptanceTester($scenario);
$I->wantTo('Проверить авторизацию на сайте.');
$I->amOnPage('/');
$I->click('Авторизация');
$I->fillField('username','Admin');
$I->fillField('password','1q2w3e');
$I->click('Войти');
$I->see('Добро пожаловать, Admin', 'h1');
И запускам тесты:
$ ./vendor/bin/codecept run acceptance
При успешном выполнении увидим такой результат:
Acceptance Tests (1) ---------------------------------------------------
✔ AuthPageCept: Perform actions and see result (0.01s)
---------------------------------------------------
Time: 168 ms, Memory: 12.25MB
OK (1 test, 0 assertions)
Настройка покрытия кода
Для формирования HTML и XML отчётов включаем утилиту coverage в файле codeception.yml и указываем какие файлы должны попасть в отчет:
coverage:
enabled: true
whitelist:
include:
- app/*
exclude:
- app/commands/*
- app/config/*
- app/migrations/*
blacklist:
include:
- app/migrations/*
exclude:
- app/services/Sendler.php
Где whitelist - это перечень файлов которые будут включены в отчет (даже если не затронуты), а blacklist - это перечень файлов которые не будут включены в отчет (даже если затронуты). Опции include и exclude здесь добавляют или удаляют файлы.
Запускаем тесты с формированием отчетов:
$ ./vendor/bin/codecept run --coverage --html --xml
После успешного выполнения тестов мы видим что-то подобное:
- HTML report generated in file:///home/user/projects/projectName/tests/_output/report.html
- XML report generated in file:///home/user/projects/projectName/tests/_output/report.xml
Это адреса файлов с отчетами тестирования. Можем перейти и посмотреть на них. Но если мы хотим посмотреть отчет о покрытии тестами файлов проекта, тогда запускаем тесты так:
$ ./vendor/bin/codecept run --coverage-html
А файл с отчетом смотрим по адресу projectName/tests/_output/coverage/index.html.
Отладка тестов
При отладке тестов часто нужно больше информации, чем просто значение о выполнении / не выполнении теста. Например, для функциональных тестов нужно увидеть получаемые заголовки. Для этого у Codeception есть параметр --debug, который покажет такую информацию:
$ ./vendor/bin/codecept run --debug
Что касается модульных тестов то, например, нужно узнать что за объект получен, а функция var_dump() игнорируется. Даже когда параметр --debug указан. В этом случае у Codeception есть своя функция отображения структурированной информации:
\Codeception\Util\Debug::debug('текст или массив');
Заключение
Таким образом с помощью Codeception мы смогли не только протестировать отдельные классы проекта, но также проверить взаимосвязь всех его компонентов и корректную работу в браузере. А благодаря утилите coverage увидеть какие части приложения протестированы, а какие нет.