Глава 2.8: Тестирование API
Время изучения: 1 час
1. Зачем нужны тесты?
Представьте, что вы построили космический корабль. Прежде чем отправлять его на Марс, вы проводите тысячи проверок на Земле. Тесты в программировании — это то же самое. Они:
- Дают уверенность: Вы можете менять код, и если тесты проходят — значит, вы ничего не сломали.
- Экономят время: Вместо того чтобы вручную "прокликивать" все в Postman после каждого изменения, вы запускаете одну команду, и она проверяет все за вас за секунды.
- Служат документацией: Хорошие тесты показывают, как должен работать ваш API.
2. Настройка тестовой "Лаборатории"
Laravel делает настройку тестов невероятно простой. По умолчанию, он использует отдельную конфигурацию, чтобы не затронуть вашу основную базу данных.
База данных для тестов:
По умолчанию Laravel использует базу данных в оперативной памяти (:memory:
). Это самый быстрый способ, потому что не нужно ничего писать на диск. База создается перед тестами и уничтожается после них. Нам даже не нужно ничего настраивать для этого!
Создание тестового файла: Давайте создадим специальный файл для тестов, связанных с планетами.
Эта команда создаст файл 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. Запуск тестов
Теперь, когда тесты написаны, запустить их очень просто. Выполните в терминале:
Laravel найдет все ваши тесты и выполнит их один за другим. Если все пройдет успешно, вы увидите зеленый вывод. Если какой-то тест провалится, вы увидите красный вывод с подробным описанием ошибки, что позволит вам быстро ее исправить.
Чтобы запустить только один конкретный файл:
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: Запуск с отчетом
Отчет: Откройтеcoverage/index.html
в браузере
9. Интеграция с Postman
Автоматизация через Newman:
- Экспортируйте коллекцию Postman в
tests/Postman/SpaceApi.postman_collection.json
- Установите Newman:
- Добавьте скрипт в
composer.json
: - Запуск:
Квиз для закрепления
🚀 Итог главы:
Вы провели полный цикл предполетных испытаний! Теперь ваш API:
- ✅ Настраивать тестовую среду без лишних усилий
- 🛡️ Писать тесты по принципу "Подготовка-Действие-Проверка".
- 📊 Тестировать как успешные сценарии (CRUD), так и ошибки (валидация, 404).
- 🔁 Запускать тесты одной командой и быть уверенным в своем коде.
Космический корабль к запуску готов! Вы завершили раздел по созданию API на Laravel.
📌 Финальная проверка:
- Запустите
php artisan test
- Убедитесь, что все тесты проходят (зеленый свет!)
- Проверьте отчет о покрытии
⚠️ Если тесты падают:
- Проверьте работу API через Postman
- Убедитесь, что тестовая БД настроена
- Используйте
dd($response->content())
для отладки
Поздравляем с завершением Главы 2! Вы не просто создали API, вы создали надежный и проверенный "космический корабль", готовый к дальнейшим миссиям.
🌌 Дальнейшие шаги:
- Настройка аутентификации (Sanctum)
- Документирование API с помощью Swagger
- Развертывание на сервере (Forge, VPS)
- Написание фронтенда на Vue/React
Успешного запуска вашей космической миссии! В следующей главе мы рассмотрим написание API с нуля 🚀