Знайдіть функціональні тести, які створюють записи в базі даних без звичайного оновлення бази даних у Laravel

0
Перекладено ШІ
Оригінал: Laravel News
Оновлено: 04 жовтня, 2025
При тестуванні функцій Laravel вам пропонуються ефективні інструменти для тестування бази даних, такі як trait `RefreshDatabase`. Чи знаєте ви, що забуття цього trait може викликати дивні помилки у тестах? Дізнайтеся, як уникнути цих проблем та зробити ваші тести більш надійними!

При тестуванні функцій у Laravel ви можете скористатися корисними інструментами для роботи з базами даних, такими як оновлення бази, фабрики, сидери та асерції. У сучасному Laravel-тесті на Pest, що використовує оновлення бази даних, код може виглядати так:

use Illuminate\Foundation\Testing\RefreshDatabase;

pest()->use(RefreshDatabase::class);

test('basic example', function () {
    $user = User::factory()->create();
    $response = $this->actingAs($user)->get('/');

    // ...
});

На жаль, розробники іноді можуть забувати додавати трейт RefreshDatabase, що призводить до випадкових помилок в інших тестах. Щоб уникнути цього, можна додати трейт до всіх функціональних тестів. У файлі tests/Pest.php розкоментуйте цю строку:

pest()->extend(Tests\TestCase::class)
    ->use(Illuminate\Foundation\Testing\RefreshDatabase::class)
    ->in('Feature');

Документація Laravel говорить про трейт RefreshDatabase так:

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

Таким чином, тести без цього трейту не працюватимуть у відкоті транзакцій, що може викликати дивні помилки в асерціях вашого додатку. Один із способів швидше знайти проблемні тести — використовувати grep для пошуку файлів, які не використовують RefreshDatabase, але містять виклики factory(), seed() тощо:

grep -rL 'RefreshDatabase' tests/Feature | xargs grep -l '::factory('

Ця команда відобразить файли, в яких немає трейту RefreshDatabase, але є виклики ::factory(). Якщо в нашому прикладі тесту ми видалимо трейт і виконаємо цю команду:

$ grep -rL 'RefreshDatabase' tests/Feature | xargs grep -l '::factory('

tests/Feature/ExampleTest.php

Слід зазначити, що тест без викликів ::factory() може все ще створювати записи через сидери або HTTP-запити. Ви можете просто запустити першу частину команди для більш уважного розслідування, скористатися AI або ще більше відфільтрувати. Використання першої частини початкової команди також покаже наш приклад файлу. Зазвичай цього достатньо для подальшого розслідування інших файлів:

$ grep -rL 'RefreshDatabase' tests/Feature

tests/Feature/ExampleTest.php

Ви також можете трішки поекспериментувати, щоб знайти файли без трейту RefreshDatabase, які містять один із наступних викликів:

grep -rL 'RefreshDatabase' tests/Feature \
  | xargs grep -El '::factory\(|->seed\(|->putJson\(|->postJson\(|->post\(|->put\('

Варто зауважити, що Laravel має й інші трейти для роботи з міграціями, такі як DatabaseMigrations та DatabaseTruncation. Також, якщо у вас є трейт RefreshDatabase як невикористовуваний імпорт, цей файл не буде відображено. Наведена команда не є ідеальною, але її можна налаштувати під ваші потреби.

Ви навіть можете перетворити це на GitHub workflow, який не пройде, якщо буде знайдено будь-які файли, що підпадають під вищезазначений пошук. Ваші результати можуть варіюватись, але ось уявний (не тестований) варіант GitHub workflow, який перевіряє, чи є файли, що відповідають цим умовам:

name: Check for Missing RefreshDatabase

on:
  pull_request:
    paths:
      - 'tests/Feature/**'

jobs:
  check-refresh-database:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Find files missing RefreshDatabase that use database features
        run: |
          set -e
          files=$(grep -rL 'RefreshDatabase' tests/Feature | xargs grep -El '::factory\(|->seed\(|->putJson\(|->postJson\(|->post\(|->put\(' || true)
          if [ -n "$files" ]; then
            echo "The following files are missing 'RefreshDatabase':"
            echo "$files"
            exit 1
          fi

Ще один нюанс: записи бази даних можуть бути вставлені через моделі! Як я вже згадував, цей grep пошук не ідеальний; це інструмент, що допоможе швидше знайти файл, який вставляє записи в базу даних без міграцій.

Рекомендую дотримуватись таких конвенцій:

Можливо, є й інші конвенції, про які я не згадую — будь ласка, діліться своїми інструментами для налагодження тестів у ваших улюблених соціальних мережах.

Популярні

Logomark Logotype

Створення CLI-додатка за допомогою Laravel та Docker

Зазирніть у світ Laravel, де потужний CLI-фреймворк відкриває нові можливості для розробки командного інтерфейсу. Дізнайтеся, як створити просту утиліту для перевірки акцій, яка працює з Docker, та які переваги це може принести у вашому проєкті!

Logomark Logotype

Використання повнотекстового пошуку в Laravel

Laravel пропонує потужні можливості повнотекстового пошуку за допомогою методів whereFullText та orWhereFullText, що дозволяють здійснювати складні запити до бази даних. Дізнайтеся, як реалізувати ефективний пошук для вашого блогу чи системи управління контентом

Logomark Logotype

Оптимізація запитів до бази даних за допомогою скорочених методів Laravel

Laravel пропонує зручні методи для роботи з датами, які значно спрощують запити до бази даних. Досліджуйте, як ці інтуїтивно зрозумілі функції допомагають створювати чіткі та зрозумілі умови для роботи з часовими даними!