Урок 12: Тестирование в Laravel. Unit-тесты, HTTP-тесты, работа с базой данных

Мы прошли уже 11 уроков. Научились работать с роутами, контроллерами, базами данных, Blade, Eloquent. Теперь пришло время поговорить о важнейшей части разработки, это тестировании. В этом уроке я расскажу, как писать тесты в Laravel, начиная с простых Unit-тестов и заканчивая сложными HTTP-тестами. Мы разберемся с PHPUnit, тестированием роутов, контроллеров, баз данных и даже напишем несколько практических примеров. \

Представь, что ты построил дом, но не проверил, насколько прочны его стены. Тестирование это именно та проверка. Оно помогает:

  • Находить ошибки до того, как их увидят пользователи.
  • Убедиться, что изменения в коде не сломали существующие функции.
  • Сэкономить время на ручную проверку.
  • Повысить уверенность в своем коде.

Laravel предоставляет мощные инструменты для тестирования «из коробки», и сегодня мы научимся ими пользоваться.

Настройка окружения для тестирования

Перед началом убедись, что у тебя установлен PHPUnit. В Laravel он уже включен в зависимости.
Чтобы запустить тесты, используй команду:

bash
php artisan test

Все тесты хранятся в директории tests/. По умолчанию там есть два файла:

  • Unit/ExampleTest.php — для Unit-тестов.
  • Feature/ExampleTest.php — для функциональных тестов.

Написание Unit-тестов с PHPUnit

Unit-тесты проверяют отдельные «юниты» кода, например методы классов.

Пример: Простой тест

Допустим, у нас есть класс Calculator с методом add(), который складывает два числа.
Создадим его в app/Calculator.php:

php
namespace App; 

class Calculator 
{ 
    public function add($a, $b) 
    { 
        return $a + $b; 
    } 
}

Теперь напишем тест для этого класса. Создай файл tests/Unit/CalculatorTest.php:

php
namespace Tests\Unit; 

use App\Calculator; 
use PHPUnit\Framework\TestCase; 

class CalculatorTest extends TestCase 
{ 
    public function test_add_numbers() 
    { 
        $calculator = new Calculator(); 
        $result = $calculator->add(2, 3); 
        
        $this->assertEquals(5, $result); // Проверяем, что 2 + 3 = 5 
    } 
}

Запусти тест:

bash
php artisan test --filter CalculatorTest

Если видишь зеленую надпись OK, значит, все работает!

Основные методы PHPUnit

  • assertEquals($expected, $actual) — проверяет равенство значений.
  • assertTrue($condition) — проверяет, что условие истинно.
  • assertFalse($condition) — проверяет, что условие ложно.
  • assertContains($needle, $array) — проверяет наличие элемента в массиве.

Практическая задача:
Напиши метод subtract() в классе Calculator и создай для него Unit-тест.

Тестирование роутов и контроллеров

В Laravel можно тестировать не только классы, но и маршруты с контроллерами.

Пример: Тестирование GET-запроса

Допустим, у нас есть роут:

php
Route::get('/welcome', function () { 
    return view('welcome'); 
});

Создадим тест в tests/Feature/RoutingTest.php:

php
namespace Tests\Feature; 

use Tests\TestCase; 

class RoutingTest extends TestCase 
{ 
    public function test_welcome_route() 
    { 
        $response = $this->get('/welcome'); 
        $response->assertStatus(200); // Проверяем статус 200 (OK) 
        $response->assertViewIs('welcome'); // Проверяем, что возвращается view welcome 
    } 
}

Пример: Тестирование контроллера

Предположим, у нас есть контроллер UserController с методом index(), который возвращает список пользователей.

Тест в tests/Feature/UserControllerTest.php:

php
namespace Tests\Feature; 

use Tests\TestCase; 

class UserControllerTest extends TestCase 
{ 
    public function test_user_index_returns_json() 
    { 
        $response = $this->getJson('/api/users'); 
        $response->assertStatus(200); 
        $response->assertJsonStructure(['data' => []]); // Проверяем структуру JSON 
    } 
}

Практическая задача:
Создай роут /about, который возвращает view about.blade.php, и напиши для него тест.

Тестирование баз данных

Часто нужно проверить, что данные корректно сохраняются в БД. Laravel предоставляет для этого удобные методы.

Пример: Тестирование создания пользователя

Используем фабрику для генерации тестовых данных. Создай фабрику для модели User:

bash
php artisan make:factory UserFactory --model=User

В файле database/factories/UserFactory.php:

php
use App\Models\User; 
use Illuminate\Support\Facades\Hash; 

$factory->define(User::class, function (Faker $faker) { 
    return [ 
        'name' => $faker->name, 
        'email' => $faker->unique()->safeEmail, 
        'password' => Hash::make('password'), 
    ]; 
});

Теперь напишем тест в tests/Feature/UserTest.php:

php
namespace Tests\Feature; 

use App\Models\User; 
use Illuminate\Foundation\Testing\RefreshDatabase; 
use Tests\TestCase; 

class UserTest extends TestCase 
{ 
    use RefreshDatabase; // Автоматически обновляет БД после каждого теста 

    public function test_user_creation() 
    { 
        $user = User::factory()->create(); 
        
        $this->assertDatabaseHas('users', [ 
            'email' => $user->email 
        ]); 
    } 
}

Практическая задача:
Создай модель Post с полями title и content, напиши фабрику и тест для проверки создания поста.

Примеры HTTP-тестов

HTTP-тесты позволяют имитировать запросы к приложению и проверять ответы.

Пример: Тестирование формы входа

Допустим, у нас есть маршрут /login, который принимает email и password.

Тест в tests/Feature/AuthTest.php:

php
namespace Tests\Feature; 

use App\Models\User; 
use Illuminate\Foundation\Testing\RefreshDatabase; 
use Tests\TestCase; 

class AuthTest extends TestCase 
{ 
    use RefreshDatabase; 

    public function test_user_login() 
    { 
        $user = User::factory()->create([ 
            'password' => bcrypt('password123') 
        ]); 

        $response = $this->post('/login', [ 
            'email' => $user->email, 
            'password' => 'password123' 
        ]); 

        $response->assertRedirect('/dashboard'); // Проверяем редирект 
        $this->assertAuthenticatedAs($user); // Проверяем, что пользователь авторизован 
    } 
}

Пример 6: Тестирование Middleware

Проверим, что гость не может попасть на защищенную страницу.

php
public function test_guest_cannot_access_admin() 
{ 
    $response = $this->get('/admin'); 
    $response->assertRedirect('/login'); 
}

Практическая задача:
Создай маршрут /posts, который доступен только аутентифицированным пользователям, и напиши тест для проверки доступа.

Итоги 12-го урока

Сегодня мы научились:

  • Писать Unit-тесты с PHPUnit.
  • Тестировать роуты и контроллеры.
  • Работать с тестовой базой данных.
  • Выполнять HTTP-тесты.

Тестирование это навык, который требует практики. Не ленись писать тесты для своих проектов,и ты увидишь, как улучшится качество твоего кода.

Готов погрузиться глубже? Полный курс по Laravel для начинающих