Тестування Laravel з Pest 5 у 2026: TIA, Mocking та питання співбесід
Опануйте найкращі практики тестування Laravel з Pest 5, Test Impact Analysis, Mockery, facade fakes та архітектурними тестами. Охоплює unit-тести, feature-тести, стратегії мокінгу та типові питання співбесід для Laravel-розробників.

Найкращі практики тестування Laravel суттєво змінилися з появою Pest 5, рушія TIA (Test Impact Analysis) та PHPUnit 13. Laravel 13 має першокласну підтримку Pest, що робить процес тестування більш виразним і менш громіздким порівняно з чистим PHPUnit. Цей посібник охоплює патерни, важливі як для production-застосунків, так і для технічних співбесід.
Pest 5 (побудований на PHPUnit 13) є стандартним тестовим фреймворком для Laravel 13. Він вимагає PHP 8.4+ і пропонує рушій TIA, вбудовану верифікацію AI-агентів, інтеграцію з PHPStan та time-balanced sharding.
Налаштування Pest 5 у проєкті Laravel 13
Кожен новий застосунок Laravel 13 автоматично налаштовує Pest. Для існуючих проєктів міграція з Pest 4 займає хвилини, оскільки основним питанням є сумісність з PHPUnit 13. Конфігурація міститься у файлі tests/Pest.php, де реєструються глобальні трейти та допоміжні методи.
use IlluminateFoundationTestingRefreshDatabase;
pest()
->extend(TestsTestCase::class)
->use(RefreshDatabase::class)
->in('Feature');Цей єдиний файл замінює старий трейт CreatesApplication та успадкування від базового тестового класу. Трейт RefreshDatabase обгортає кожен тест у транзакцію бази даних, автоматично відкочуючи зміни.
use AppModelsUser;
it('registers a new user with valid data', function () {
$response = $this->postJson('/api/register', [
'name' => 'Jane Doe',
'email' => 'jane@example.com',
'password' => 'SecurePass123!',
'password_confirmation' => 'SecurePass123!',
]);
$response->assertStatus(201)
->assertJsonStructure(['user' => ['id', 'name', 'email']]);
expect(User::where('email', 'jane@example.com')->exists())->toBeTrue();
});API expect() у Pest природно ланцюгується з assertions PHPUnit. Виклик assertJsonStructure валідує структуру відповіді, тоді як expect()->toBeTrue() підтверджує стан бази даних. Обидва стилі співіснують без конфліктів.
Test Impact Analysis: флагманська функція Pest 5
Рушій TIA робить Pest 5 трансформаційним для великих кодових баз. Під час першого запуску Pest записує, які тести торкаються яких файлів. Кожен наступний запуск виконує лише тести, на які вплинули зміни, і відтворює кешовані результати для решти.
# First run: records baseline (requires PCOV or Xdebug)
php artisan test
# Subsequent runs: only affected tests execute
php artisan testTest suite Laravel Cloud, що містить понад 19 000 тестів, скоротив час виконання з приблизно трьох хвилин до п'яти секунд з увімкненим TIA. Рушій розуміє більше ніж PHP-файли: він виявляє зміни в міграціях, шаблонах Blade та спільних JavaScript-компонентах.
TIA вимагає драйвера покриття (PCOV або Xdebug) для запису baseline. У CI pipeline'ах кешовані відображення зберігаються між запусками, що робить приріст продуктивності кумулятивним.
Unit-тести vs Feature-тести в Laravel
Різниця між unit та feature тестами в Laravel визначає, які частини фреймворку завантажуються. Unit-тести працюють без контейнера застосунку, що робить їх швидшими, але обмеженими чистою логікою. Feature-тести завантажують повний застосунок, забезпечуючи HTTP-виклики, запити до бази даних та розв'язання сервісів.
use AppServicesPriceCalculator;
describe('PriceCalculator', function () {
it('applies a percentage discount correctly', function () {
$calculator = new PriceCalculator();
// 20% off a 150.00 base price
$result = $calculator->applyDiscount(150.00, 20);
expect($result)->toBe(120.00);
});
it('rejects negative discount values', function () {
$calculator = new PriceCalculator();
expect(fn () => $calculator->applyDiscount(100.00, -5))
->toThrow(InvalidArgumentException::class);
});
});Unit-тести націлені на ізольовані класи без зовнішніх залежностей. Блок describe групує пов'язані assertions, і Pest 5 підтримує вкладені блоки describe для складних ієрархій тестів.
Feature-тести повинні складати більшість тестового набору Laravel. Вони виявляють інтеграційні помилки, які unit-тести пропускають, такі як неправильний middleware маршруту, відсутні правила валідації або пошкоджені зв'язки Eloquent. Загальне правило: якщо код торкається бази даних, HTTP-шару або фасаду, потрібно писати feature-тест.
Стратегії мокінгу з фасадами та Mockery
Мокінг у тестуванні Laravel ізолює тестований код від зовнішніх залежностей. Фасади Laravel надають вбудовані фейкові реалізації для черг, подій, сповіщень, пошти та сховища. Mockery обробляє все інше.
use AppModelsOrder;
use AppModelsUser;
use IlluminateSupportFacadesMail;
use IlluminateSupportFacadesQueue;
use AppMailOrderConfirmation;
use AppJobsProcessPayment;
it('dispatches payment job and sends confirmation email', function () {
// Fake both Mail and Queue facades
Mail::fake();
Queue::fake();
$user = User::factory()->create();
$order = Order::factory()->for($user)->create([
'total' => 99.99,
'status' => 'pending',
]);
// Act: confirm the order via HTTP
$this->actingAs($user)
->postJson("/api/orders/{$order->id}/confirm")
->assertOk();
// Assert: payment job was dispatched with correct amount
Queue::assertPushed(ProcessPayment::class, function ($job) use ($order) {
return $job->order->id === $order->id
&& $job->order->total === 99.99;
});
// Assert: confirmation email was sent to the user
Mail::assertSent(OrderConfirmation::class, function ($mail) use ($user) {
return $mail->hasTo($user->email);
});
});Facade fakes перехоплюють виклики на рівні фреймворку, запобігаючи фактичному надсиланню emails або dispatch jobs. Assertions на основі замикань перевіряють точні дані, передані кожному компоненту.
Уникайте мокінгу внутрішніх доменних класів. Мокайте на межах: сторонні API, пошта, черги, файлові системи. Надмірний мокінг робить тести крихкими та тісно пов'язаними з деталями реалізації.
Для залежностей, які не є фасадами, інжектуйте їх через конструктор і використовуйте Mockery:
use AppServicesPaymentGateway;
use AppServicesStripeClient;
it('charges the customer through the payment gateway', function () {
// Create a mock of the Stripe client
$stripeClient = Mockery::mock(StripeClient::class);
$stripeClient->shouldReceive('charge')
->once()
->with('cus_abc123', 5000, 'usd')
->andReturn(['status' => 'succeeded', 'id' => 'ch_xyz']);
// Bind the mock in the container
$this->app->instance(StripeClient::class, $stripeClient);
$gateway = app(PaymentGateway::class);
$result = $gateway->processCharge('cus_abc123', 50.00);
expect($result['status'])->toBe('succeeded');
});Прив'язка мока через $this->app->instance() замінює реальну реалізацію на час тесту. Mockery перевіряє, що charge було викликано рівно один раз з очікуваними аргументами.
Архітектурні тести з пресетами Pest
Pest 5 включає архітектурне тестування, яке забезпечує структурні правила по всій кодовій базі. Ці тести працюють з AST, а не з runtime, що робить їх надзвичайно швидкими.
arch('controllers do not use Eloquent directly')
->expect('AppHttpControllers')
->not->toUse('IlluminateDatabaseEloquent');
arch('services are final classes')
->expect('AppServices')
->toBeFinal();
arch('no debugging functions in production code')
->expect(['dd', 'dump', 'var_dump', 'ray'])
->not->toBeUsed();Перше правило забороняє контролерам напряму звертатися до бази даних, примушуючи використовувати патерн сервісного шару. Друге гарантує, що сервіси не можуть бути розширені, зменшуючи складність успадкування. Третє виявляє залишені debug-інструкції до потрапляння в production.
Також доступні пресети, специфічні для Laravel:
arch()->preset()->laravel();
arch()->preset()->security();
arch()->preset()->php();Ці три рядки забезпечують десятки правил: моделі розширюють правильний базовий клас, контролери не містять бізнес-логіки, немає небезпечних функцій на кшталт eval() чи md5() для хешування, та дотримуються стандартні конвенції PHP.
Готовий до співбесід з Laravel?
Практикуйся з нашими інтерактивними симуляторами, flashcards та технічними тестами.
Mutation testing для перевірки якості тестів
Code coverage вимірює, які рядки виконуються під час тестів. Mutation testing йде далі: він модифікує вихідний код і перевіряє, чи тести виявляють зміну. Якщо мутація виживає, тестовий набір має прогалину.
# Run mutation testing on a specific class
php artisan test --mutate --class=App\Services\PriceCalculatorPest 5 вводить мутації, такі як зміна > на >=, видалення інструкцій return та інверсія булевих умов. Mutation score нижче 80% зазвичай вказує, що тести перевіряють результати без перевірки крайніх випадків.
// Example: this test has high coverage but low mutation score
it('calculates shipping cost', function () {
$cost = calculateShipping(weight: 5.0, zone: 'domestic');
// Only checks that the result is numeric
expect($cost)->toBeFloat();
});
// Improved: catches mutations by asserting the exact value
it('calculates domestic shipping for 5kg package', function () {
$cost = calculateShipping(weight: 5.0, zone: 'domestic');
// Exact assertion catches operator and value mutations
expect($cost)->toBe(12.50);
});Перший тест проходить, навіть якщо логіка обчислення повністю неправильна, поки вона повертає float. Другий тест одразу падає, коли мутація змінює формулу. Специфічні assertions дають вищі mutation scores.
Патерни тестування бази даних та фабрики
Фабрики моделей Laravel генерують реалістичні тестові дані без ручного створення масивів. Pest 5 у поєднанні з фабриками забезпечує читабельну, легку в підтримці конфігурацію даних.
use AppModelsArticle;
use AppModelsUser;
it('publishes a draft article and updates the timestamp', function () {
$author = User::factory()->create(['role' => 'editor']);
$article = Article::factory()
->for($author, 'author')
->draft()
->create(['title' => 'Testing Best Practices']);
$this->actingAs($author)
->patchJson("/api/articles/{$article->id}/publish")
->assertOk()
->assertJsonPath('data.status', 'published');
$article->refresh();
expect($article->status)->toBe('published')
->and($article->published_at)->not->toBeNull()
->and($article->published_at->isToday())->toBeTrue();
});Стан фабрики draft() встановлює значення за замовчуванням для неопублікованих статей. Ланцюгові assertions expect() з ->and() читаються як природна мова і падають з описовими повідомленнями.
Запустіть php artisan test --parallel для виконання тестів у кількох процесах. Laravel автоматично створює окремі тестові бази даних для кожного процесу, запобігаючи конфліктам даних. Time-balanced sharding у Pest 5 розподіляє тести за фактичним часом виконання, а не за кількістю, забезпечуючи завершення кожного CI shard в один момент.
Типові питання співбесід про тестування Laravel
Технічні співбесіди на позиції Laravel часто перевіряють знання тестування. Ось питання, які з'являються найчастіше, разом з ключовими пунктами відповіді.
Яка різниця між fake(), mock() та spy() у тестуванні Laravel?
Фасадний fake() замінює весь фасад in-memory реалізацією (Mail::fake, Queue::fake). mock() через Mockery встановлює очікування перед виконанням і падає, якщо вони не виконуються. spy() записує взаємодії та дозволяє assertions після виконання, без встановлення попередніх очікувань. Вибір залежить від того, чи тест повинен перевіряти поведінку (mock), записувати взаємодії (spy) чи запобігати побічним ефектам (fake).
Чим відрізняється RefreshDatabase від DatabaseTransactions?
RefreshDatabase запускає міграції один раз і обгортає кожен тест у транзакцію. DatabaseTransactions припускає, що база даних вже має правильну схему, і лише обгортає тести в транзакції. RefreshDatabase безпечніший для CI pipeline'ів, де база даних може ще не існувати. DatabaseTransactions швидший, коли схема гарантовано актуальна.
Коли віддавати перевагу feature-тестам над unit-тестами?
Feature-тести повинні покривати будь-який код, який взаємодіє з HTTP-шаром, базою даних або сервісами Laravel. Unit-тести зарезервовані для чистих функцій та value objects без залежностей від фреймворку. У типовому Laravel-застосунку feature-тести переважають над unit-тестами у співвідношенні приблизно 3:1 або вище. Це відображає реальність, що більша частина коду Laravel за своєю природою інтегрована з фреймворком.
Як Test Impact Analysis покращує продуктивність CI?
TIA записує, які тести торкаються яких вихідних файлів під час першого запуску. При наступних запусках Pest виконує лише тести, на які вплинули змінені файли, і відтворює кешовані результати для незмінних тестів. Великі набори, які займали хвилини, можуть завершитися за секунди. Компроміс: TIA вимагає драйвера покриття (PCOV або Xdebug) для побудови карти залежностей, і перший запуск займає більше часу, ніж звичайний.
Як mutation testing покращує якість тестів понад code coverage?
Code coverage вимірює шляхи виконання. Тест може досягти 100% coverage, викликаючи кожен метод без будь-яких значущих assertions. Mutation testing модифікує вихідний код (змінюючи оператори, видаляючи return, інвертуючи булеві значення) і перевіряє, що принаймні один тест падає. Мутації, що вижили, виявляють надто слабкі або повністю відсутні assertions. Запуск php artisan test --mutate видає відсоток mutation score поряд зі стандартним coverage.
Більше питань співбесід Laravel можна знайти в банку питань SharpSkill, який охоплює автентифікацію, патерни service container, зв'язки Eloquent та архітектуру черг.
Тестування HTTP-відповідей та JSON assertions
HTTP testing helpers Laravel перевіряють status codes, headers, структури JSON та цілі redirect. У поєднанні з Pest вони формують лаконічні інтеграційні тести.
use AppModelsUser;
describe('API Authentication', function () {
it('rejects unauthenticated requests with 401', function () {
$this->getJson('/api/profile')
->assertUnauthorized();
});
it('returns the authenticated user profile', function () {
$user = User::factory()->create([
'name' => 'John Doe',
'email' => 'john@example.com',
]);
$this->actingAs($user)
->getJson('/api/profile')
->assertOk()
->assertJson([
'data' => [
'name' => 'John Doe',
'email' => 'john@example.com',
],
]);
});
it('validates required fields on registration', function () {
$this->postJson('/api/register', [])
->assertUnprocessable()
->assertJsonValidationErrors(['name', 'email', 'password']);
});
});Блок describe групує тести, пов'язані з автентифікацією. Кожна назва тесту описує очікувану поведінку, а не реалізацію. Метод assertJsonValidationErrors перевіряє, що конкретні поля мають повідомлення про помилки валідації.
Джерела
- Pest 5 Released by Laravel News, announcing TIA engine, Agent plugin, and Evals
- Pest 5 Now Available, official documentation with requirements and new features
- What We Know About Laravel 13, covering PHP Attributes, AI SDK, and March 2026 release
- PHPUnit 13 Release Announcement, detailing new assertions and deprecations
Ключові висновки про тестування Laravel з Pest 5
- Pest 5 з Laravel 13 усуває boilerplate завдяки fluent API конфігурації, ланцюгам
expect()та автоматичному виявленню тестів - Рушій TIA перезапускає лише affected тести, скорочуючи виконання великих наборів з хвилин до секунд без втрати точності coverage
- Feature-тести повинні складати ядро тестового набору Laravel, з unit-тестами, зарезервованими для ізольованої бізнес-логіки
- Facade fakes (
Mail::fake(),Queue::fake()) обробляють мокінг на рівні фреймворку, тоді як Mockery обробляє сторонні залежності, інжектовані через контейнер - Архітектурні тести забезпечують структурні правила (без Eloquent у контролерах, без debug-функцій) без runtime overhead
- Mutation testing з
--mutateвиявляє слабкі assertions, які сам code coverage пропускає - Factory states та ланцюгові assertions
expect()->and()зберігають конфігурацію тестових даних читабельною, а assertions специфічними - Для підготовки до співбесід Laravel розуміння mock/fake/spy, поведінки
RefreshDatabase, TIA та mutation testing демонструє зрілість тестування понад базовий coverage
Починай практикувати!
Перевір свої знання з нашими симуляторами співбесід та технічними тестами.
Чи знайдеш ти помилку в Laravel?
Справжній фрагмент коду, прихована помилка, одна спроба на день. Щоб спробувати, акаунт не потрібен.

Автор:
Anthony Fillion-MailletЗасновник SharpSkill
Fullstack-розробник понад 10 років. Керує SharpSkill і відповідає за все, що тут публікується.
Оновлено 2 вересня 2026 р.
Теги
Поділитися
Пов'язані статті

Питання на співбесіду PHP Laravel Developer 2026: Повний посібник з підготовки
Комплексний посібник з технічних питань на співбесіду для PHP Laravel розробників у 2026 році. Охоплює Eloquent ORM, Service Container, авторизацію, черги та тестування.

Laravel 12 у 2026 році: нові можливості, Starter Kits та питання для співбесіди
Повний огляд Laravel 12: перероблені Starter Kits на основі React 19, Vue 3, Svelte 5 та Livewire 4, інтеграція WorkOS AuthKit, оновлення залежностей до Carbon 3 та PHP 8.2+, покроковий посібник з оновлення з Laravel 11 та актуальні питання для технічних співбесід у 2026 році.

Рішення Laravel: Розширені Патерни, Налагодження та Питання на Співбесіді 2026
Комплексний посібник з розширених архітектурних патернів Laravel, технік налагодження з Telescope та найпоширеніших питань на співбесідах для розробників Laravel.