Введение
Laravel предоставляет очень удобный API для создания HTTP-запросов к вашему приложению, проверки вывода, и даже заполнения форм. Например, посмотрим на приведённый тест:
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class ExampleTest extends TestCase
{
/**
* Пример базового теста функции.
*
* @return void
*/
public function testBasicExample()
{
$this->visit('/')
->see('Laravel 5')
->dontSee('Rails');
}
}
Метод PHPvisit()
делает GET-запрос в приложение. Метод PHPsee()
объявляет, что мы должны увидеть данный текст в отклике приложения. Метод PHPdontSee()
объявляет, что данный текст не возвращается в отклике приложения. Это самый базовый тест приложения в Laravel.
Вы можете использовать метод PHPvisitRoute()
, чтобы выполнить GET-запрос через именованный маршрут:
$this->visitRoute('profile');
$this->visitRoute('profile', ['user' => 1]);
Взаимодействие со ссылками
В этом тесте мы сделаем запрос в приложение, «нажмём» ссылку в возвращённом отклике, а затем проверим, что оказались на нужном URI. Например, предположим, что в нашем отклике есть ссылка с текстом «О нас»:
xml<a href="/about-us">О нас</a>
Теперь давайте напишем тест, нажимающий ссылку и проверяющий переход пользователя на правильную страницу:
public function testBasicExample()
{
$this->visit('/')
->click('О нас')
->seePageIs('/about-us');
}
Вы можете проверить, что пользователь достиг корректный именованный маршрут, методом %%seeRouteIs():
->seeRouteIs('profile', ['user' => 1]);
Взаимодействие с формами
Также Laravel предоставляет несколько методов для тестирования форм. Методы PHPtype()
, PHPselect()
, PHPcheck()
, PHPattach()
и PHPpress()
позволяют вам взаимодействовать со всеми элементами ввода на ваших формах. Например, представим, что на странице регистрации в приложении есть такая форма:
xml<form action="/register" method="POST"> {{ csrf_field() }} <div> Name: <input type="text" name="name"> </div> <div> <input type="checkbox" value="yes" name="terms"> Accept Terms </div> <div> <input type="submit" value="Register"> </div> </form>
Мы можем написать тест для заполнения этой формы и проверки результата:
public function testNewUserRegistration()
{
$this->visit('/register')
->type('Taylor', 'name')
->check('terms')
->press('Register')
->seePageIs('/dashboard');
}
Если ваша форма содержит другие элементы ввода, такие как радио-кнопки и выпадающие списки, вы так же легко можете заполнить такие типы полей. Вот список всех методов для работы с формами:
Метод | Описание |
---|---|
$this->type($text, $elementName) | Ввести текст в данное поле |
$this->select($value, $elementName) | Выбрать радио-кнопку или выпадающее поле |
$this->check($elementName) | Поставить чекбокс |
$this->uncheck($elementName) | Снять чекбокс |
$this->attach($pathToFile, $elementName) | Прикрепить файл к форме |
$this->press($buttonTextOrElementName) | Нажать кнопку с заданным текстом или именем |
Если на вашей форме есть элементы ввода типа file, вы можете прикрепить файлы к форме методом PHPattach()
:
public function testPhotoCanBeUploaded()
{
$this->visit('/upload')
->attach($pathToFile, 'photo')
->press('Upload')
->see('Upload Successful!');
}
Тестирование JSON API
Также Laravel предоставляет несколько вспомогательных функций для тестирования JSON API и их откликов. Например, методы PHPjson()
, PHPget()
, PHPpost()
, PHPput()
, PHPpatch()
и PHPdelete()
используются для выполнения различных HTTP-запросов. Вы также легко можете передать данные и заголовки в эти методы. Для начала давайте напишем тест, выполняющий POST-запрос к /user и проверяющий, что возвращаются ожидаемые данные:
<?php
class ExampleTest extends TestCase
{
/**
* Пример базового теста функции.
*
* @return void
*/
public function testBasicExample()
{
$this->json('POST', '/user', ['name' => 'Sally'])
->seeJson([
'created' => true,
]);
}
}
Метод PHPseeJson()
конвертирует данный массив в JSON, а затем проверяет, что фрагмент JSON появляется где-либо внутри полного JSON-отклика, возвращаемого приложением. Поэтому, если в нём будут ещё и другие свойства, этот тест всё равно будет пройден успешно, так как данный фрагмент присутствует в отклике.
Проверка на точное совпадение
Если вы хотите проверить точное совпадение данного массива с возвращённым из приложения JSON, вам надо использовать метод PHPseeJsonEquals()
:
<?php
class ExampleTest extends TestCase
{
/**
* Пример базового теста функции.
*
* @return void
*/
public function testBasicExample()
{
$this->json('POST', '/user', ['name' => 'Sally'])
->seeJsonEquals([
'created' => true,
]);
}
}
Проверка на совпадение структуры
Также можно проверить соответствие структуры JSON определённым требованиям. В этом случае используйте метод PHPseeJsonStructure()
и передайте в него ожидаемую JSON-структуру:
<?php
class ExampleTest extends TestCase
{
/**
* Пример базового функционального теста.
*
* @return void
*/
public function testBasicExample()
{
$this->get('/user/1')
->seeJsonStructure([
'name',
'pet' => [
'name', 'age'
]
]);
}
}
В этом примере ожидается получение атрибута name и вложенного объекта pet с его собственными атрибутами name и age. Метод PHPseeJsonStructure()
выполнится без ошибки, если в отклике будут дополнительные ключи. Например, проверка будет пройдена и в том случае, когда pet будет иметь атрибут weight.
Вы можете использовать *, чтобы задать требование, что возвращаемая структура JSON должна содержать список, в котором каждый элемент содержит по крайней мере те атрибуты, которые есть в наборе значений:
<?php
class ExampleTest extends TestCase
{
/**
* A basic functional test example.
*
* @return void
*/
public function testBasicExample()
{
// Требование, что каждый user в списке должен иметь как минимум атрибуты id, name и email.
$this->get('/users')
->seeJsonStructure([
'*' => [
'id', 'name', 'email'
]
]);
}
}
Вы можете использовать вложение *. Тогда мы потребуем, что каждый user в JSON отклике должен содержать заданный набор атрибутов, и каждый pet каждого user также должен содержать заданный набор атрибутов:
$this->get('/users')
->seeJsonStructure([
'*' => [
'id', 'name', 'email', 'pets' => [
'*' => [
'name', 'age'
]
]
]
]);
Сессии / Аутентификация
В Laravel есть несколько функций для работы с сессиями во время тестирования. Сначала вы можете задать данные сессии для данного массива при помощи метода PHPwithSession()
. Это полезно для загрузки сессии с данными перед выполнением тестового запроса в приложение:
<?php
class ExampleTest extends TestCase
{
public function testApplication()
{
$this->withSession(['foo' => 'bar'])
->visit('/');
}
}
Конечно, чаще всего сессии используют для поддержания нужного состояния аутентифицированного пользователя. Простой способ аутентифицировать данного пользователя в качестве текущего — метод PHPactingAs()
. Например, мы можем использовать фабрику модели, чтобы сгенерировать и аутентифицировать пользователя:
<?php
class ExampleTest extends TestCase
{
public function testApplication()
{
$user = factory(App\User::class)->create();
$this->actingAs($user)
->withSession(['foo' => 'bar'])
->visit('/')
->see('Hello, '.$user->name);
}
}
Вторым аргументом метода PHPactingAs()
вы можете указать защитника для аутентификации данного пользователя:
$this->actingAs($user, 'api')
Отключение посредников
При тестировании приложения иногда удобно отключить посредников для некоторых тестов. Это позволит вам тестировать маршруты и контроллер изолированно от любых влияний посредников. Laravel содержит простой типаж WithoutMiddleware, который можно использовать для автоматического отключения всех посредников для класса теста:
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class ExampleTest extends TestCase
{
use WithoutMiddleware;
//
}
Если захотите отключить посредников только для некоторых тестовых методов, можете вызвать метод PHPwithoutMiddleware()
из тестовых методов:
<?php
class ExampleTest extends TestCase
{
/**
* Пример базового теста функции.
*
* @return void
*/
public function testBasicExample()
{
$this->withoutMiddleware();
$this->visit('/')
->see('Laravel 5');
}
}
Свои HTTP-запросы
Если вы хотите сделать свой HTTP-запрос в приложение и получить полный объект Illuminate\Http\Response, используйте метод PHPcall()
:
public function testApplication()
{
$response = $this->call('GET', '/');
$this->assertEquals(200, $response->status());
}
Если вы делаете запросы POST, PUT или PATCH, то можете передать массив входных данных вместе с запросом. Тогда эти данные будут доступны в ваших маршрутах и контроллере через экземпляр запроса:
$response = $this->call('POST', '/user', ['name' => 'Taylor']);
Проверки PHPUnit (assertions)
Laravel предоставляет несколько assert-методов для тестов PHPUnit:
Метод | Описание |
---|---|
->assertResponseOk(); | Проверка того, что клиентский отклик имеет статус ОК. |
->assertResponseStatus($code); | Проверка того, что клиентский отклик имеет указанный статус. |
->assertViewHas($key, $value = null); | Проверка того, что представление в отклике содержит данный кусок привязанных данных. |
->assertViewHasAll(array $bindings); | Проверка того, что представление содержит данный список привязанных данных. |
->assertViewMissing($key); | Проверка того, что в представлении в отклике отсутствует данный кусок привязанных данных. |
->assertRedirectedTo($uri, $with = []); | Проверка того, что клиент был переадресован по данному URI. |
->assertRedirectedToRoute($name, $parameters = [], $with = []); | Проверка того, что клиент был переадресован по данному маршруту |
->assertRedirectedToAction($name, $parameters = [], $with = []); | Проверка того, что клиент был переадресован к данному действию |
->assertSessionHas($key, $value = null); | Проверка того, что в сессии есть данное значение. |
->assertSessionHasAll(array $bindings); | Проверка того, что в сессии есть данный список значений. |
->assertSessionHasErrors($bindings = [], $format = null); | Проверка того, что в сессии есть привязанные ошибки. |
->assertHasOldInput(); | Проверка того, что в сессии есть введённые ранее данные. |
->assertSessionMissing($key); | Проверка того, что в сессии нет указанного ключа. |