Junior: питання на співбесіді з теми «Тестування»
Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.
3 питання
Factory (фабрика) генерує фейкові дані моделей через Faker. Незамінна в тестах і сідерах.
class PostFactory extends Factory
{
public function definition(): array
{
return [
'title' => fake()->sentence(),
'body' => fake()->paragraphs(3, true),
];
}
}
Post::factory()->count(10)->create(); // 10 записів у БД
Post::factory()->published()->make(); // стан + без збереження
«Стани» (states) дозволяють описати варіації, наприклад ->published() чи ->trashed().
Різниця в тому, скільки застосунку бере участь у тесті.
Feature-тест (tests/Feature) піднімає весь Laravel: маршрути, middleware, базу, контейнер. Він перевіряє поведінку так, як її бачить користувач:
it('creates an order', function () {
$user = User::factory()->create();
$this->actingAs($user)
->post('/orders', ['product_id' => 1])
->assertRedirect('/orders');
expect($user->orders)->toHaveCount(1);
});
Unit-тест (tests/Unit) перевіряє один клас ізольовано й не завантажує застосунок - отже, там немає фасадів, конфігурації й бази. Він підходить для чистої логіки:
it('calculates the discount', function () {
expect((new PriceCalculator)->withDiscount(1000, 10))->toBe(900);
});
Як обирати: у Laravel-застосунку більшість цінних тестів - feature: вони ловлять помилки на стиках, де їх найбільше, і не ламаються від рефакторингу внутрішніх класів. Unit-тести - для алгоритмів, розрахунків і класів без залежностей від фреймворку, де вони швидкі й точно вказують на поломку.
Тест створюють командою php artisan make:test, з --unit для unit-тесту.
Скидати базу між тестами. Laravel дає для цього трейти.
RefreshDatabase - стандартний вибір. Він мігрує базу один раз на прогін, а кожен тест загортає в транзакцію й відкочує її наприкінці. Швидко, бо таблиці не перестворюються.
// tests/Pest.php
pest()->extend(Tests\TestCase::class)
->use(Illuminate\Foundation\Testing\RefreshDatabase::class)
->in('Feature');
LazilyRefreshDatabase - те саме, але мігрує лише тоді, коли тест справді звернувся до бази. Тести без бази стають швидшими.
DatabaseMigrations і DatabaseTruncation скидають базу повністю: перестворюють чи очищують таблиці. Значно повільніше - потрібні, коли код сам керує транзакціями чи з'єднаннями, і обгортка RefreshDatabase йому заважає.
Що ще ділять тести, крім бази:
- кеш і сесію - у тестах їх тримають на драйвері
array, що живе один запит; - статичні властивості й синглтони, які пережили тест;
- файли - тому для дисків беруть
Storage::fake().
Ознака проблеми: тести проходять поодинці, але падають разом чи в іншому порядку.
Докладніше в документації: Скидання бази після кожного тесту