Как писать тесты в Laravel

Laravel Тесты

В этом уроке мы расскажем о том, как начать писать функциональные тесты PHPUnit в Laravel.

Давайте рассмотрим блог-приложение, где есть модель Post и она имеет поля title и body. Давайте напишем функциональный тест в стиле TDD (Test-Driven Development — Разработка через тестирование), чтобы проверить функциональность модели.

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

Прежде, чем мы начнем писать наш первый тест, поймите, что мы нам не нужно тестировать нашу базу данных, так как в ней могут быть тонны пользовательских записей и другой информации.

Для тестов мы должны иметь возможность брать точные данные, которые необходимы для работы конкретного теста.

Для этого мы внесем изменения в настройки тестовой базы данных, которая будет использоваться для тестирования phpunit. Откройте файл phpunit.xml, который находится в корневой папке вашего проекта, и добавьте в конец файла следующие свойства в переменные окружения.

<env name="APP_ENV" value="testing"/>
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>

Значение :memory: переменной DB_DATABASE говорит sqlite, что мы используем не реальные файлы, а работаем в памяти.

Отлично, теперь мы готовы написать первый функциональный тест.

Откройте вашу IDE и перейдите в папку tests/Feature.

Tests Feature

Обратите внимание, что в папке уже есть файл ExampleTest.php. Здесь мы и создадим новый тест.

Для этого перейдите в терминал/командную строку и выполните следующую команду.

php artisan make:test PostsTest

В папке tests/Feature появится новый тест под названием PostsTest.php со следующим кодом

namespace Tests\Feature;

use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;

class PostsTest extends TestCase
{
    /**
     * A basic test example.
     *
     * @return void
     */
    public function testExample()
    {
        $this->assertTrue(true);
    }
}

Давайте изменим его и поработаем в стиле TDD.

Модифицируйте ваш PostsTest как показано ниже.

namespace Tests\Feature;

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Tests\TestCase;

class PostsTest extends TestCase
{
    use DatabaseMigrations;
    /**
     * A basic test example.
     *
     * @return void
     */

    /** @test  */
    public function a_user_can_browse_posts()
    {
        $response = $this->get('/posts');

        $response->assertStatus(200);
    }
}

Мы используем DatabaseMigrations, это обеспечит запуск миграций при каждом запуске теста. И, как только тест завершится, миграции откатятся обратно. И помните, что миграция делаются прямо в память, как мы задали в файле phpunit.xml.

Мы переименовали нашу функцию в a_user_can_browse_posts и обратите внимание на комментарий /** @test */ в верхней части функции. Это важно, так как по нему phpunit распознает наш тест во время работы.

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

vendor/bin/phpunit

Тест не пройден с ошибкой

1) Tests\Feature\PostsTest::a_user_can_browse_posts
Expected status code 200 but received 404.
Failed asserting that false is true.

Это было ожидаемо, ведь в файле web.php еще нет маршрута для /posts.

Давайте его добавим. Перейдите в файл web.php и добавьте следующий маршрут.

Route::get('/posts', 'PostsController@index');

Запустите тест снова и он должен выдать зеленое сообщение

Пример успешного теста в Laravel

Все идёт отлично. Давайте теперь изменим этот тест, так как пока он нам только говорит, что страница /posts работает. Нам нужно убедиться, что на этой странице мы также видим сообщения.

Откройте PostController.php и измените метод index для получения сообщений и передачи их в шаблон.

public function index()
{
    $posts = Post::latest()->get();
    return view('posts.index',compact('posts'));
}

Теперь нам нужно создать шаблон index.blade.php в папке resources/views/posts

@extends('layouts.app')

@section('content')
    <div class="container">
        <div class="row justify-content-center">
            <div class="col-md-8">
                <div class="card">
                <div class="card-header">Posts</div>
                    <div class="card-body">
                       @foreach($posts as $post)
                           {{$post->title}}<br/>
                           {{$post->body}}
                            <hr/>
                        @endforeach
                    </div>
                </div>
            </div>
        </div>
    </div>
@endsection

Изменим наш тест для проверки того, что мы видим сообщения на странице /posts.

/** @test  */
public function a_user_can_browse_posts()
{
    $post = factory('App\Post')->create();
    
    $response = $this->get('/posts');

    $response->assertSee($post->title);
}

Запустите тест еще раз, он должен выдать зеленое сообщение. Готово! Мы написали свой первый функциональный тест в Laravel.

Автор: tgugnani
Перевод: Demiurge Ash