
Як використовувати SQLite для тестування в Laravel
22.05.2019 19:31 | Laravel
Трохи загальної інформації про тестування в Laravel і про те, як використовувати для цих цілей SQLite.
ОС: Ubuntu 18.04. Laravel: 5.8. SQLite: 3.22
Про тестування
Підтримка phpunit в Laravel вже вбудована, включаючи налаштування в файлі phpunit.xml
. У корені проекту знаходиться директорія tests
c двома піддиректоріями - Feature
і Unit
. Якщо вже зовсім коротко, то:
- Unit тести (вони ж модульні тести) призначені для тестування окремого, ізольованого модуля (наприклад, методу, функції) з усіма mockup-залежностями.
- Feature тести (функціональні тести, інтеграційні тести) потрібні для тестування будь-якої частини функціоналу системи, можуть взаємодіяти з базами даних, сервісами і т.д. Можуть перевіряти взаємодію об'єктів один з одним, HTTP-запити і т.д.
Простіше кажучи: є дві сутності - категорія і товар. Ми написали тести, які перевіряють кожну з них - це модульні тести. Якщо ж хочемо перевірити як ці сутності взаємодіють і чи нічого не зламається - пишемо функціональні тести.
Модульні тести створюються командою:
php artisan make:test MyModuleTest --unit
Для створення функціонального тесту слід виконати:
php artisan make:test MyFeatureTest
Методи в класах тестів повинні починатися зі слова test
(причому для назви методу може Використовувати як camelCase, так і snake_case), або над методом повинен бути прописаний php dockblock @test
. Приклади валидного коду:
public function testUserCanCreatePost() {}
public function test_user_can_create_post() {}
/**
* @test
*/
public function userCanCreatePost() {}
Запускаються тести з кореня проекту командою:
vendor/bin/phpunit
Можна запускати як тест окремого класу, так і тестувати будь-якої окремий метод. Дані опції відносяться не до Laravel, а до PHPUnit, тому як завжди пропоную ознайомитися с документацією.
Важливо: недонократно стикався з тим, що люди забувають про те, що тести повинні бути незалежними. Іншими словами, кожен метод кожного тестового класу повинен працювати в незалежності від того, чи були запущені інші тести чи ні. Помилка, що часто зустрічається - один метод покладається на якусь частину коду, яка була написана в одному з попередніх методів. Наприклад, в методі є такий код:
$user = factory(User::class)->state('admin')->create();
$this->actingAs($user)
І наступний метод розраховуватими на те, що дії будуть виконані користувачем-адміном.
Що стосується оточення - при запуску тестів, фреймворк автоматично встановить змінні середовища, які визначені в phpunit.xml
. Також для сесій і кеша драйвером буде встановлено масив, відповідно дані сесій і кешу не будуть зберігатися. Ще одна опція - створити файл .env.testing
і вказати в ньому змінні, які треба перевизначити під час тестування. Слід згадати рекомендацію (з оф доків) обов'язково очищати кеш конфігурації перед запуском тестів:
php artisan config:clear
Використання SQLite
Що стосується тестів, які потребують "спілкування" з базами даних, - особисто я на практиці стикався з двома варіантами. Перший - просто створюється база даних для тестування. Використовуємо в проекті PostgreSQL - значить створюємо тестову базу PostgreSQL, використовуємо MySQL - створимо тестову базу MySQL і т.д. Хоча тести займають більше часу, але при такому підході ми можемо бути впевнені, що не виникне ніяких нюансів, пов'язаних з різною реалізацією (вибачте за тавтологію) різних баз даних.
Другий варіант - використання SQLite in memory. Тобто фізично база даних не створюється - всі дані під час тестування зберігаються в пам'яті, що позитивно позначається на тривалості виконання тестів. Треба визнати, що даний спосіб досить поширений, оскільки в реальному житті не так часто розробники використовують ті можливості БД, які не дозволяють підмінити використовувану базу на SQLite при тестуванні.
Почнемо з установки. Оновимо кеш репозиторія пакетів apt:
sudo apt-get update
Потім поставимо SQLite 3:
sudo apt-get install sqlite3
Перевіримо, чи працює SQLite:
sqlite3 --version
В результаті виконання команди ми повинні побачити приблизно наступне:
3.22.0 2018-01-22 18:45:57 0c55d179733b46d8d0ba4d88e01a25e10677046ee3da1d5b1581e86726f2alt1
Виконайте:
php -i|grep PDO
Якщо не бачите PDO драйвера для SQLite, то знадобиться ще одна команда для його інсталяції під Вашу версію php (в моєму випадку 7.3):
sudo apt-get install php7.3-sqlite3
Якщо є бажання, таже можна поставити графічну оболонку SQLite Browser (після установки для запуску цього інструменту треба зайти в меню додатків і набрати в поле пошуку SQLite Browser, вибрати його і натиснути Enter):
sudo apt-get install sqlitebrowser
Як використовувати в Laravel тестах
В розділ Database Connections файлу config/database.php
додамо:
'sqlite_memory' => [
'driver' => 'sqlite',
'database' => ':memory:',
'prefix' => '',
]
Потім пропишемо пару рядків в phpunit.xml
:
<env name="DB_CONNECTION" value="sqlite_memory"/>
<env name="DB_DATABASE" value=":memory:"/>
Примітка: якщо в проекті використовується Telescope, також слід додати і такий рядок:
<env name="TELESCOPE_ENABLED" value="false"/>
Тобто блок php
файлу буде виглядати так:
<php>
<env name="APP_ENV" value="testing"/>
<env name="DB_CONNECTION" value="sqlite_memory"/>
<env name="DB_DATABASE" value=":memory:"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="MAIL_DRIVER" value="array"/>
<env name="QUEUE_CONNECTION" value="sync"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="TELESCOPE_ENABLED" value="false"/>
</php>
І останнє - для запуску міграцій додамо трейт DatabaseMigrations
:
<?php
namespace Tests;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
use CreatesApplication, DatabaseMigrations;
}
На цьому все. Успіхів!