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

Присоединяйся к нашему Telegram сообществу @webblend!

Здесь ты найдешь сниппеты по Laravel и полезные советы по веб-разработке.

Введение

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

Сброс базы данных после каждого теста

Прежде чем двигаться дальше, давайте обсудим, как сбросить вашу базу данных после каждого теста, чтобы данные предыдущего теста не мешали последующим тестам. Встроенный трейт Laravel Illuminate\Foundation\Testing\RefreshDatabase сделает это за вас. Просто используйте трейт в вашем классе теста:

<?php
 
namespace Tests\Feature;
 
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
 
class ExampleTest extends TestCase
{
use RefreshDatabase;
 
/**
* Пример базового функционального теста.
*/
public function test_basic_example(): void
{
$response = $this->get('/');
 
// ...
}
}

Трейт Illuminate\Foundation\Testing\RefreshDatabase не мигрирует вашу базу данных, если ваша схема актуальна. Вместо этого он выполнит тест в пределах транзакции базы данных. Таким образом, любые записи, добавленные в базу данных тестовыми случаями, которые не используют этот трейт, могут по-прежнему существовать в базе данных.

Если вы хотите полностью сбросить базу данных, вы можете использовать трейты Illuminate\Foundation\Testing\DatabaseMigrations или Illuminate\Foundation\Testing\DatabaseTruncation. Однако оба эти варианта значительно медленнее трейта RefreshDatabase.

Фабрики моделей

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

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

use App\Models\User;
 
public function test_models_can_be_instantiated(): void
{
$user = User::factory()->create();
 
// ...
}

Запуск сидеров

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

<?php
 
namespace Tests\Feature;
 
use Database\Seeders\OrderStatusSeeder;
use Database\Seeders\TransactionStatusSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
 
class ExampleTest extends TestCase
{
use RefreshDatabase;
 
/**
* Тест создания нового заказа.
*/
public function test_orders_can_be_created(): void
{
// Запуск DatabaseSeeder...
$this->seed();
 
// Запуск определенного сидера...
$this->seed(OrderStatusSeeder::class);
 
// ...
 
// Запуск массива определенных сидеров...
$this->seed([
OrderStatusSeeder::class,
TransactionStatusSeeder::class,
// ...
]);
}
}

Кроме того, вы можете указать Laravel автоматически заполнять базу данных перед каждым тестом, который использует трейт RefreshDatabase. Вы можете сделать это, определив свойство $seed в вашем базовом классе теста:

<?php
 
namespace Tests;
 
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
 
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
 
/**
* Указывает, должен ли выполняться сидер по умолчанию перед каждым тестом.
*
* @var bool
*/
protected $seed = true;
}

Когда свойство $seed установлено в true, тест будет выполнять класс Database\Seeders\DatabaseSeeder перед каждым тестом, использующим трейт RefreshDatabase. Однако вы можете указать конкретный сидер для выполнения, определив свойство $seeder в вашем классе теста:

use Database\Seeders\OrderStatusSeeder;
 
/**
* Запускает определенный сидер перед каждым тестом.
*
* @var string
*/
protected $seeder = OrderStatusSeeder::class;

Доступные утверждения

Laravel предоставляет несколько утверждений для базы данных в ваших PHPUnit тестах. Мы рассмотрим каждое из этих утверждений ниже.

assertDatabaseCount

Утверждает, что таблица в базе данных содержит заданное количество записей:

$this->assertDatabaseCount('users', 5);

assertDatabaseHas

Утверждает, что таблица в базе данных содержит записи, соответствующие заданным ограничениям запроса по ключу / значению:

$this->assertDatabaseHas('users', [
'email' => '[email protected]',
]);

assertDatabaseMissing

Утверждает, что таблица в базе данных не содержит записей, соответствующих заданным ограничениям запроса по ключу / значению:

$this->assertDatabaseMissing('users', [
'email' => '[email protected]',
]);

assertSoftDeleted

Метод assertSoftDeleted можно использовать для утверждения, что заданная модель Eloquent была "мягко удалена":

$this->assertSoftDeleted($user);

assertNotSoftDeleted

Метод assertNotSoftDeleted можно использовать для утверждения, что заданная модель Eloquent не была "мягко удалена":

$this->assertNotSoftDeleted($user);

assertModelExists

Утверждает, что заданная модель существует в базе данных:

use App\Models\User;
 
$user = User::factory()->create();
 
$this->assertModelExists($user);

assertModelMissing

Утверждает, что заданная модель не существует в базе данных:

use App\Models\User;
 
$user = User::factory()->create();
 
$user->delete();
 
$this->assertModelMissing($user);

expectsDatabaseQueryCount

Метод expectsDatabaseQueryCount можно вызвать в начале вашего теста, чтобы указать общее количество запросов к базе данных, которые вы ожидаете выполнения во время теста. Если фактическое количество выполненных запросов не соответствует ожиданиям, тест не пройдет:

$this->expectsDatabaseQueryCount(5);
 
// Тест...