Skip to content

Глава 2.8: Тестирование API

Время изучения: 1 час


1. Зачем нужны тесты?

Представьте, что вы построили космический корабль. Прежде чем отправлять его на Марс, вы проводите тысячи проверок на Земле. Тесты в программировании — это то же самое. Они:

  • Дают уверенность: Вы можете менять код, и если тесты проходят — значит, вы ничего не сломали.
  • Экономят время: Вместо того чтобы вручную "прокликивать" все в Postman после каждого изменения, вы запускаете одну команду, и она проверяет все за вас за секунды.
  • Служат документацией: Хорошие тесты показывают, как должен работать ваш API.

2. Настройка тестовой "Лаборатории"

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

База данных для тестов: По умолчанию Laravel использует базу данных в оперативной памяти (:memory:). Это самый быстрый способ, потому что не нужно ничего писать на диск. База создается перед тестами и уничтожается после них. Нам даже не нужно ничего настраивать для этого!

Создание тестового файла: Давайте создадим специальный файл для тестов, связанных с планетами.

php artisan make:test PlanetApiTest

Эта команда создаст файл tests/Feature/PlanetApiTest.php. Слово Feature означает, что мы будем тестировать функциональность в целом (например, "может ли пользователь создать планету?"), а не отдельный маленький класс.


3. Анатомия теста: Подготовка, Действие, Проверка

Откройте tests/Feature/PlanetApiTest.php. Внутри мы напишем наш первый тест. Хороший тест всегда состоит из трех частей (Arrange, Act, Assert).

<?php

namespace Tests\Feature;

use App\Models\Planet; // Не забудьте импортировать модель
use Illuminate\Foundation\Testing\RefreshDatabase; // Важнейший инструмент!
use Tests\TestCase;

class PlanetApiTest extends TestCase
{
    // Этот трейт "волшебным образом" очищает и пересоздает
    // нашу тестовую базу данных перед каждым тестом.
    // Это гарантирует, что тесты не влияют друг на друга.
    use RefreshDatabase;

    /**
     * Тест: эндпоинт для получения списка планет работает корректно.
     * Названия тестов должны быть осмысленными!
     */
    public function test_can_get_all_planets(): void
    {
        // 1. ПОДГОТОВКА (Arrange)
        // Создаем 3 фейковые планеты в нашей тестовой базе данных
        // с помощью фабрики, которую мы создали ранее.
        Planet::factory()->count(3)->create();

        // 2. ДЕЙСТВИЕ (Act)
        // Имитируем настоящий GET-запрос к нашему API.
        $response = $this->getJson('/api/planets');

        // 3. ПРОВЕРКА (Assert)
        // Проверяем, что все прошло как надо.
        $response->assertStatus(200); // Ожидаем, что сервер ответил "200 OK"
        $response->assertJsonCount(3); // Ожидаем, что в ответе ровно 3 планеты
    }
}
Ключевые моменты:

  • use RefreshDatabase: Этот трейт — ваш лучший друг. Он гарантирует, что каждый тест начинается с "чистого листа", с пустой базой данных.
  • Planet::factory(): Фабрики идеально подходят для создания тестовых данных.
  • $this->getJson(): Это специальный метод Laravel для отправки API-запросов внутри тестов.
  • assert...(): Это "утверждения" или "проверки". Если хотя бы одна из них не выполнится, тест провалится.

4. Тестирование основных операций (CRUD)

Давайте напишем тесты для создания, обновления и удаления планет.

A. Тест на создание планеты (POST)

<?php
public function test_can_create_a_planet(): void
{
    // 1. Подготовка: готовим данные для новой планеты
    $planetData = [
        'name' => 'Kepler-186f',
        'description' => 'Первая экзопланета размером с Землю в обитаемой зоне.',
        'size_km' => 14000,
        'solar_system' => 'Kepler-186'
    ];

    // 2. Действие: отправляем POST-запрос с данными
    $response = $this->postJson('/api/planets', $planetData);

    // 3. Проверка
    $response->assertStatus(201); // Ожидаем статус "201 Created"
    $response->assertJsonFragment(['name' => 'Kepler-186f']); // Проверяем, что в ответе есть созданное имя

    // Самая важная проверка: действительно ли данные попали в базу?
    $this->assertDatabaseHas('planets', [
        'name' => 'Kepler-186f'
    ]);
}

B. Тест на удаление планеты (DELETE)

<?php
public function test_can_delete_a_planet(): void
{
    // 1. Подготовка: создаем планету, которую будем удалять
    $planet = Planet::factory()->create();

    // 2. Действие: отправляем DELETE-запрос
    $response = $this->deleteJson("/api/planets/{$planet->id}");

    // 3. Проверка
    $response->assertStatus(204); // Ожидаем "204 No Content" - успешное удаление

    // Проверяем, что запись действительно исчезла из базы
    $this->assertDatabaseMissing('planets', [
        'id' => $planet->id
    ]);
}


5. Тестирование "плохих" сценариев

Тестировать успешные случаи — это хорошо. Но еще важнее тестировать ошибки!

A. Тест на ошибку валидации

<?php
public function test_creation_fails_with_invalid_data(): void
{
    // 2. Действие: отправляем заведомо некорректные данные
    $response = $this->postJson('/api/planets', ['name' => '']); // Пустое имя

    // 3. Проверка
    $response->assertStatus(422); // Ожидаем "422 Unprocessable Entity"
    $response->assertJsonValidationErrors('name'); // Ожидаем, что ошибка именно в поле 'name'
}

B. Тест на "не найдено" (404)

<?php
public function test_returns_404_for_non_existent_planet(): void
{
    // 2. Действие: запрашиваем планету с несуществующим ID
    $response = $this->getJson('/api/planets/99999');

    // 3. Проверка
    $response->assertStatus(404); // Ожидаем "404 Not Found"
}


6. Запуск тестов

Теперь, когда тесты написаны, запустить их очень просто. Выполните в терминале:

php artisan test

Laravel найдет все ваши тесты и выполнит их один за другим. Если все пройдет успешно, вы увидите зеленый вывод. Если какой-то тест провалится, вы увидите красный вывод с подробным описанием ошибки, что позволит вам быстро ее исправить.

Чтобы запустить только один конкретный файл:

php artisan test tests/Feature/PlanetApiTest.php


8. Покрытие кода (Code Coverage)

Шаг 1: Установка Xdebug

Для сбора информации о покрытии кода требуется расширение PHP — Xdebug.

Отправьте в wizard ваш php -i и следуйте инструкциям.

Шаг 2: Настройка phpunit.xml

<phpunit ... >
    <coverage processUncoveredFiles="true">
        <include>
            <directory suffix=".php">./app</directory>
        </include>
    </coverage>
</phpunit>

Шаг 3: Запуск с отчетом

php artisan test --coverage-html=coverage
Отчет: Откройте coverage/index.html в браузере


9. Интеграция с Postman

Автоматизация через Newman:

  1. Экспортируйте коллекцию Postman в tests/Postman/SpaceApi.postman_collection.json
  2. Установите Newman:
    npm install -g newman
    
  3. Добавьте скрипт в composer.json:
    "scripts": {
        "test:postman": "newman run tests/Postman/SpaceApi.postman_collection.json"
    }
    
  4. Запуск:
    composer test:postman
    

Квиз для закрепления

1. Команда для создания тестового класса:

2. Трейт RefreshDatabase используется для:

3. Метод для проверки JSON-структуры:

4. Фабрики в Laravel нужны для:

5. Инструмент для запуска Postman-коллекций из CLI:


🚀 Итог главы:

Вы провели полный цикл предполетных испытаний! Теперь ваш API:

  • ✅ Настраивать тестовую среду без лишних усилий
  • 🛡️ Писать тесты по принципу "Подготовка-Действие-Проверка".
  • 📊 Тестировать как успешные сценарии (CRUD), так и ошибки (валидация, 404).
  • 🔁 Запускать тесты одной командой и быть уверенным в своем коде.

Космический корабль к запуску готов! Вы завершили раздел по созданию API на Laravel.

📌 Финальная проверка:

  1. Запустите php artisan test
  2. Убедитесь, что все тесты проходят (зеленый свет!)
  3. Проверьте отчет о покрытии

⚠️ Если тесты падают:

  • Проверьте работу API через Postman
  • Убедитесь, что тестовая БД настроена
  • Используйте dd($response->content()) для отладки

Поздравляем с завершением Главы 2! Вы не просто создали API, вы создали надежный и проверенный "космический корабль", готовый к дальнейшим миссиям.

🌌 Дальнейшие шаги:

  1. Настройка аутентификации (Sanctum)
  2. Документирование API с помощью Swagger
  3. Развертывание на сервере (Forge, VPS)
  4. Написание фронтенда на Vue/React

Успешного запуска вашей космической миссии! В следующей главе мы рассмотрим написание API с нуля 🚀