Функциональные тесты
Теперь, когда мы написали некоторые приемочные тесты, функциональные тесты почти такие же, с одним важным отличием: функциональные тесты не требуют веб-сервера.
Под капотом Codeception использует BrowserKit Symfony для «отправки» запросов к вашему приложению. Таким образом, реальный HTTP-запрос не выполняется, а вместо этого в контроллер фреймворка (передним) передается объект Request BrowserKit с необходимыми свойствами.
В качестве первого шага вам необходимо включить модуль Codeception для вашего фреймворка в functional.suite.yml (см. ниже).
Все модули фреймворка Codeception разделяют один и тот же интерфейс, и, следовательно, ваши тесты не привязаны ни к одному из них. Вот пример функционального теста:
<?php
// LoginCest.php
class LoginCest
{
public function tryLogin(FunctionalTester $I)
{
$I->amOnPage('/');
$I->click('Login');
$I->fillField('Username', 'Miles');
$I->fillField('Password', 'Davis');
$I->click('Enter');
$I->see('Hello, Miles', 'h1');
// $I->seeEmailIsSent(); // only for Symfony
}
} Как видите, синтаксис одинаков для функциональных и приемочных тестов.
Ограничения
Функциональные тесты обычно намного быстрее, чем приемочные тесты. Но функциональные тесты менее стабильны, так как они запускают Codeception и приложение в одной среде. Если ваше приложение не было разработано для работы в долгоживущих процессах (например, если вы используете оператор exit или глобальные переменные), то функциональные тесты, вероятно, не для вас.
Заголовки, куки, сессии
Одна из распространенных проблем с функциональными тестами — использование функций PHP, которые работают с заголовками, сессиями и куками. Как вы, возможно, уже знаете, функция header вызывает ошибку, если она выполняется после того, как PHP уже вывел что-то. В функциональных тестах приложение запускается несколько раз, поэтому мы получим много нерелевантных ошибок в результате.
Внешние URL-адреса
Функциональные тесты не могут получить доступ к внешним URL-адресам, только к URL-адресам внутри вашего проекта. Вы можете использовать PhpBrowser для открытия внешних URL-адресов.
Общий доступ к памяти
При функциональном тестировании, в отличие от запуска приложения традиционным способом, приложение PHP не останавливается после завершения обработки запроса. Поскольку все запросы выполняются в одном контейнере памяти, они не изолированы. Поэтому если вы видите, что ваши тесты загадочно терпят неудачу, когда этого не должно быть — попробуйте выполнить один тест. Это покажет, терпят ли тесты неудачу из-за того, что они не были изолированы во время выполнения. Держите память чистой, избегайте утечек памяти и очищайте глобальные и статические переменные.
Включение модулей фреймворка
У вас есть набор функциональных тестов в каталоге tests/functional. Для начала необходимо включить один из модулей фреймворка в файл конфигурации набора: tests/functional.suite.yml.
Symfony
Для выполнения интеграции Symfony вам просто нужно включить модуль Symfony в ваш набор тестов. Если вы также используете Doctrine2, не забудьте включить его тоже. Чтобы модуль Doctrine2 подключался с помощью службы doctrine из Symfony, вы должны указать модуль Symfony как зависимость для Doctrine2:
# functional.suite.yml
actor: FunctionalTester
modules:
enabled:
- Symfony
- Doctrine2:
depends: Symfony # connect to Symfony По умолчанию этот модуль будет искать AppKernel в каталоге app.
Модуль использует Symfony Profiler для предоставления дополнительной информации и утверждений.
Laravel5
Модуль Laravel5 включен и не требует конфигурации:
# functional.suite.yml
actor: FunctionalTester
modules:
enabled:
- Laravel5 Yii2
Тесты Yii2 включены в шаблоны приложений Basic и Advanced. Следуйте руководствам Yii2 для начала.
Zend Framework 2
Используйте модуль ZF2 для запуска функциональных тестов внутри Zend Framework 2:
# functional.suite.yml
actor: FunctionalTester
modules:
enabled:
- ZF2 Zend Expressive
Zend Expressive тесты могут быть выполнены при включении соответствующего модуля.
# functional.suite.yml
actor: FunctionalTester
modules:
enabled:
- ZendExpressive См. справочник по модулям для получения дополнительных параметров конфигурации
Phalcon 4
Модуль Phalcon4 требует создания файла bootstrap, который возвращает экземпляр \Phalcon\Mvc\Application. Чтобы начать написание функциональных тестов с поддержкой Phalcon, вы должны включить модуль Phalcon4 и указать путь к этому файлу bootstrap:
# functional.suite.yml
actor: FunctionalTester
modules:
enabled:
- Phalcon4:
bootstrap: 'app/config/bootstrap.php'
cleanup: true
savepoints: true Написание функциональных тестов
Функциональные тесты пишутся так же, как и Приемочные тесты с включенным модулем PhpBrowser. Все модули фреймворка и модуль PhpBrowser разделяют одни и те же методы и один и тот же движок.
Поэтому мы можем открыть веб-страницу с помощью метода amOnPage:
<?php
$I->amOnPage('/login'); Мы можем нажимать ссылки для открытия веб-страниц:
<?php
$I->click('Logout');
// click link inside .nav element
$I->click('Logout', '.nav');
// click by CSS
$I->click('a.logout');
// click with strict locator
$I->click(['class' => 'logout']); Мы также можем отправлять формы:
<?php
$I->submitForm('form#login', ['name' => 'john', 'password' => '123456']);
// alternatively
$I->fillField('#login input[name=name]', 'john');
$I->fillField('#login input[name=password]', '123456');
$I->click('Submit', '#login'); И выполнять утверждения:
<?php
$I->see('Welcome, john');
$I->see('Logged in successfully', '.notice');
$I->seeCurrentUrlEquals('/profile/john'); Модули фреймворка также содержат дополнительные методы для доступа к внутренним компонентам фреймворка. Например, модули Laravel5, Phalcon и Yii2 имеют метод seeRecord, который использует слой ActiveRecord для проверки того, что запись существует в базе данных.
Посмотрите полную справку по используемому модулю. Большинство его методов являются общими для всех модулей, но некоторые из них уникальны.
Вы также можете получить доступ к глобальным переменным фреймворка внутри теста или получить доступ к контейнеру внедрения зависимостей внутри класса Helper\Functional:
<?php
namespace Helper;
class Functional extends \Codeception\Module
{
function doSomethingWithMyService()
{
$service = $this->getModule('Symfony')->grabServiceFromContainer('myservice');
$service->doSomething();
}
} Также проверьте все доступные Публичные свойства используемых модулей для получения полного доступа к их данным.
Отчет об ошибках
По умолчанию Codeception использует уровень отчета об ошибках E_ALL & ~E_STRICT & ~E_DEPRECATED. В функциональных тестах вы можете изменить этот уровень в зависимости от политики обработки ошибок вашего фреймворка. Уровень отчета об ошибках можно установить в файле конфигурации набора:
actor: FunctionalTester ... error_level: E_ALL & ~E_STRICT & ~E_DEPRECATED
error_level также можно установить глобально в файле codeception.yml. Для этого необходимо указать error_level в качестве части settings. Дополнительную информацию см. в Глобальной конфигурации. Обратите внимание, что значение error_level для конкретного набора тестов переопределит глобальное значение.
Заключение
Функциональные тесты отлично подходят, если вы используете мощные фреймворки. Используя функциональные тесты, вы можете получить доступ и манипулировать их внутренним состоянием. Это делает ваши тесты короче и быстрее. В других случаях, если вы не используете фреймворки, нет практической причины для написания функциональных тестов. Если вы используете фреймворк, отличный от перечисленных здесь, создайте для него модуль и поделитесь им с сообществом.
- Следующая глава: UnitTests >
- Предыдущая глава: < Приемочные тесты
© 2011 Michael Bodnarchuk and contributors
Licensed under the MIT License.
https://codeception.com/docs/04-FunctionalTests