Может войдёшь?
Черновики Написать статью Профиль

Тестирование БД

перевод документация 5.х

  1. 1. Введение
  2. 2. Сброс БД после каждого теста
    1. 2.1. Использование миграций
    2. 2.2. Использование транзакций
  3. 3. Создание фабрик
    1. 3.1. Состояния фабрик
  4. 4. Использование фабрик
    1. 4.1. Создание моделей
    2. 4.2. Постоянные модели
    3. 4.3. Отношения
Этот перевод актуален для англоязычной документации на (ветка 5.3). Опечатка? Выдели и нажми Ctrl+Enter.

Введение

Laravel предоставляет множество полезных инструментов для тестирования ваших приложений, использующих БД. Во-первых, вы можете использовать вспомогательный метод PHPseeInDatabase() для проверки того, что данные в БД соответствуют определённому набору критериев. Например, если вы хотите проверить, что в таблице users есть запись с полем email равным sally@example.com, вы можете сделать следующее:

PHP
public function testDatabase()
{
  
// Осуществление вызова приложения...

  
$this->seeInDatabase('users', [
    
'email' => 'sally@example.com'
  
]);
}

Само собой, такие методы как PHPseeInDatabase() созданы для удобства. Вы можете использовать любые встроенные методы проверки PHPUnit для дополнения своих тестов.

Сброс БД после каждого теста

Зачастую бывает полезно сбрасывать вашу БД после каждого теста, чтобы данные из предыдущего теста не влияли на последующие тесты.

Использование миграций

Один из способов сброса состояния БД — откатывать БД после каждого теста и мигрировать её перед следующим тестом. Laravel предоставляет простой типаж DatabaseMigrations, который автоматически сделает это для вас. Просто используйте этот типаж на классе вашего теста, и всё будет сделано за вас:

PHP
<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use 
Illuminate\Foundation\Testing\DatabaseMigrations;
use 
Illuminate\Foundation\Testing\DatabaseTransactions;

class 
ExampleTest extends TestCase
{
  use 
DatabaseMigrations;

  
/**
   * Пример базового функционального теста.
   *
   * @return void
   */
  
public function testBasicExample()
  {
    
$this->visit('/')
         ->
see('Laravel 5');
  }
}

Использование транзакций

Другой способ сброса состояния БД — обернуть каждый тест-кейс в транзакцию БД. И для этого Laravel также предоставляет удобный типаж DatabaseTransactions, который автоматически сделает это для вас:

PHP
<?php

use Illuminate\Foundation\Testing\WithoutMiddleware;
use 
Illuminate\Foundation\Testing\DatabaseMigrations;
use 
Illuminate\Foundation\Testing\DatabaseTransactions;

class 
ExampleTest extends TestCase
{
  use 
DatabaseTransactions;

  
/**
   * Пример базового функционального теста.
   *
   * @return void
   */
  
public function testBasicExample()
  {
    
$this->visit('/')
         ->
see('Laravel 5');
  }
}

По умолчанию этот типаж будет оборачивать в транзакции только подключение к БД по умолчанию. Если ваше приложение использует несколько подключений к БД, вам надо определить свойство PHP$connectionsToTransact в классе вашего теста. Это свойство должно быть массивом имён подключений для выполнения транзакций над ними.

Создание фабрик

При тестировании вам может понадобиться вставить несколько записей в вашу БД перед выполнением теста. При создании этих данных Laravel позволяет вам вместо указания значений каждого столбца вручную определить стандартный набор атрибутов для каждой из ваших моделей Eloquent с помощью фабрик. Для начала посмотрите на файл database/factories/ModelFactory.php в вашем приложении. Изначально этот файл содержит определение одной фабрики:

PHP
$factory->define(App\User::class, function (Faker\Generator $faker) {
  static 
$password;

  return [
    
'name' => $faker->name,
    
'email' => $faker->unique()->safeEmail,
    
'password' => $password ?: $password bcrypt('secret'),
    
'remember_token' => str_random(10),
  ];
});

В замыкании, которое служит определением фабрики, вы можете вернуть стандартные тестовые значения всех атрибутов модели. Замыкание получит экземпляр PHP-библиотеки Faker, которая позволяет вам удобно генерировать различные случайные данные для тестирования.

Само собой, вы можете добавить свои собственные дополнительные фабрики в файл ModelFactory.php. Также вы можете создать дополнительные файлы фабрик для каждой модели для более понятной организации. Например, вы можете создать файлы UserFactory.php и CommentFactory.php в вашей папке database/factories. Все файлы в папке factories будут автоматически загружены Laravel.

Состояния фабрик

Состояния позволяют вам определить отдельные изменения, которые можно применять к вашим фабрикам моделей в любых комбинациях. Например, ваша модель User может иметь состояние delinquent (нарушитель), которое изменяет стандартное значение одного из атрибутов. Вы можете определить свои преобразования состояния с помощью метода PHPstate():

PHP
$factory->state(App\User::class, 'delinquent', function ($faker) {
  return [
    
'account_status' => 'delinquent',
  ];
});

Использование фабрик

Создание моделей

После определения фабрик вы можете использовать глобальную функцию PHPfactory() в своих тестах или файлах начальных данных для генерирования экземпляров модели. Итак, давайте рассмотрим несколько примеров создания моделей. Во-первых, мы используем метод PHPmake() для создания моделей, но не сохраним их в БД:

PHP
public function testDatabase()
{
  
$user factory(App\User::class)->make();

  
// Использование модели в тестах...
}

Также вы можете создать коллекцию моделей или создать модели определённого типа:

PHP
// Создание трёх экземпляров App\User...
$users factory(App\User::class, 3)->make();

Применение состояний

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

PHP
$users factory(App\User::class, 5)->states('delinquent')->make();

$users factory(App\User::class, 5)->states('premium''delinquent')->make();

Переопределение атрибутов

Если вы хотите переопределить некоторые из стандартных значений ваших моделей, вы можете передать массив значений в метод PHPmake(). Будут заменены только указанные значения, а остальные будут заданы в соответствии с указанными в фабрике:

PHP
$user factory(App\User::class)->make([
  
'name' => 'Abigail',
]);

Постоянные модели

Метод PHPcreate() не только создаёт экземпляры моделей, но также сохраняет их в БД с помощью метода Eloquent PHPsave():

PHP
public function testDatabase()
{
  
// Создание одного экземпляра App\User...
  
$user factory(App\User::class)->create();

  
// Создание трёх экземпляров App\User...
  
$users factory(App\User::class, 3)->create();

  
// Использование модели в тестах...
}

Вы можете переопределить атрибуты модели, передав массив в метод PHPcreate():

PHP
$user factory(App\User::class)->create([
  
'name' => 'Abigail',
]);

Отношения

В этом примере мы прикрепим отношение к некоторым созданным моделям. При использовании метода PHPcreate() для создания нескольких моделей возвращается экземпляр коллекции Eloquent, позволяя вам использовать все удобные функции для работы с коллекцией, такие как PHPeach():

PHP
$users factory(App\User::class, 3)
        ->
create()
        ->
each(function ($u) {
          
$u->posts()->save(factory(App\Post::class)->make());
        });

Отношения и атрибуты замыкания

Также вы можете прикреплять отношения к моделям с помощью атрибутов замыкания в определениях ваших фабрик. Например, если вы хотите создать новый экземпляр модели User при создании Post, то можете сделать так:

PHP
$factory->define(App\Post::class, function ($faker) {
  return [
    
'title' => $faker->title,
    
'content' => $faker->paragraph,
    
'user_id' => function () {
      return 
factory(App\User::class)->create()->id;
    }
  ];
});

Это замыкание также получает определённый массив атрибутов фабрики, которая его содержит:

PHP
$factory->define(App\Post::class, function ($faker) {
  return [
    
'title' => $faker->title,
    
'content' => $faker->paragraph,
    
'user_id' => function () {
      return 
factory(App\User::class)->create()->id;
    },
    
'user_type' => function (array $post) {
      return 
App\User::find($post['user_id'])->type;
    }
  ];
});

Как вы считаете, полезен ли этот материал? Да Нет

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.