При тестуванні функцій у 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 пошук не ідеальний; це інструмент, що допоможе швидше знайти файл, який вставляє записи в базу даних без міграцій.
Рекомендую дотримуватись таких конвенцій:
RefreshDatabase у ваших тестах, коли це можливо. Це швидше, ніж очищення бази даних та стандартний (не транзакційний) трейт міграції бази.RefreshDatabase.Можливо, є й інші конвенції, про які я не згадую — будь ласка, діліться своїми інструментами для налагодження тестів у ваших улюблених соціальних мережах.