Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама
Новини 09 вересня 2026

Знайдіть несподівані тестові дані за допомогою Fuzz для Pest

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

За допомогою Fuzz - пакета від Джона Пурвіса - ви можете робити це всередині тесту Pest 5. Пакет використовує PHP-Fuzzer від nikic для зміни рядків, які ви надаєте, і повідомлення про будь-які збої через Pest.

Що означає Coverage-Guided

Фазер змінює вхідні дані, додаючи, видаляючи або замінюючи частини рядка. Потім він запускає ваш код зі зміненими даними.

Coverage-guided фазер також відстежує, якими маршрутами ці дані проходять через ваш код. Коли вхідні дані досягають раніше недослідженого маршруту, фазер зберігає їх і використовує для створення нових варіацій. Збережена колекція називається корпусом.

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

PHP-Fuzzer збирає цей зворотний зв'язок, відстежуючи переходи між блоками PHP-коду та приблизну частоту їх виконання. Fuzz обробляє це автоматично; вам не потрібен Xdebug або опція --coverage Pest.

Ви обираєте код для виклику. Fuzz пробує згенеровані рядки, поки не знайде збій або не досягне ліміту запусків. Успішний прохід означає, що він не знайшов збоїв у цих спробах; помилки все ще можуть залишатися.

Спробуємо в Pest

Fuzz потребує PHP 8.4+ та Pest 5. Встановіть його через Composer:

composer require jonpurvis/fuzz --dev

Припустимо, ваш застосунок читає обмеження швидкості на кшталт 100/60s, що означає 100 запитів за 60 секунд. Цей хелпер конвертує його в запити за секунду, але не валідує вхідні дані:

namespace App;
final class RateLimit
{
    public static function perSecond(string $spec): float
    {
        $parts = explode('/', $spec);
        $count = (int) $parts[0];
        $window = (int) rtrim($parts[1] ?? '1s', 's');
        return $count / $window;
    }
}

Збережіть хелпер у app/RateLimit.php. У tests/Unit/RateLimitTest.php визначте функцію поза тестом для виклику хелпера:

use App\RateLimit;
use function Fuzz\fuzz;

$target = static function (string $input): void {
    RateLimit::perSecond($input);
};

test('rate limit spec parser never fatals', function () use ($target): void {
    fuzz($target)
        ->seed(['100/60s', '5/1s', '1000/3600s'])
        ->withDictionary(['/', 's', '0', '1'])
        ->runs(2000)
        ->maxLen(16)
        ->run('rate-limit-parser');
});

Рядки, передані в seed(), є початковими прикладами. withDictionary() надає фрагменти, які фазер може вставляти, не обмежуючи його цими символами. runs(2000) встановлює бюджет пошуку, а maxLen(16) обмежує згенеровані рядки до 16 байтів.

Дайте кожному фаз-тесту власну назву в run(). Fuzz використовує цю назву для розділення збережених даних і файлів збоїв.

Залишайте функцію $target поза test(), як показано. При перевірці Fuzz v1.0.1 цей обгортка записувала покриття, тоді як передача Closure::fromCallable() безпосередньо не записувала нічого. Fuzz запускає функцію в окремому PHP-процесі, де згенерований Pest клас тестів недоступний. Визначення її поза test() уникає залежності від цього класу.

Запустіть тест як зазвичай:

./vendor/bin/pest tests/Unit/RateLimitTest.php

Під час нашого запуску Fuzz знайшов 5/. Відсутнє вікно стає порожнім рядком, який PHP приводить до 0. Ділення на нього викидає DivisionByZeroError, і Pest повідомляє, що тест провалився. Ваш запуск може знайти інші дані або зайняти іншу кількість спроб.

Fuzz зберігає дані, що призвели до збою, у .pest/fuzz-crashes/ за замовчуванням. Ви можете прочитати цей файл для відтворення збою. Після виправлення парсера додайте ці дані до іменованого датасету та перевірте очікувану поведінку, щоб та сама помилка не пройшла непоміченою.

Що перевіряє тест

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

Fuzz повідомляє про помилки типу TypeError, а також непридушені PHP-попередження та повідомлення. Звичайні винятки ігноруються за замовчуванням, включаючи винятки валідації Laravel. Метод allow() дозволяє звузити цей список, коли несподівані винятки мають провалювати тест. Ви також можете встановити тайм-аут для кожних даних через timeout(), що потребує розширення PHP pcntl.

Використання Fuzz поряд з вашими тестами

Зберігайте свої звичайні тести та датасети для відомих випадків та очікуваних результатів. Fuzz корисний, коли код приймає більше можливих вхідних даних, ніж ви можете розумно перелічити, наприклад, парсер, що читає текст від користувачів.

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

Почніть з невеликого бюджету запусків у вашому звичайному наборі. Якщо вам потрібен довший пошук, запускайте його в заплановій CI-роботі. README Fuzz охоплює решту опцій, включаючи словники та власні директорії зберігання.

4

Читати в документації

Коментарі

Увійдіть, щоб залишити коментар

Будьте першим, хто залишить коментар!

Читайте також

PayZephyr
Новини 12 вересня 2026

PayZephyr: Єдиний API для роботи з Stripe, Paystack та PayPal

PayZephyr - Laravel-пакет від Nwaneri Chukwunyere Kenneth, який об'єднує вісім платіжних провайдерів під одним зручним API. Підтримує автоматичне перемикання, захист від подвійної оплати, підписки та повернення коштів.

2
Laravel Telescope
Новини 11 вересня 2026

Artisan-команди для дебагу в Laravel Telescope 5.24.0

Laravel Telescope 5.24.0 додає дві нові Artisan-команди для роботи із записами із терміналу. Тепер можна переглядати запити, винятки, джоби та запити до бази даних без відкриття веб-інтерфейсу, а також отримувати дані у форматі JSON для скриптів та AI-агентів.

3

Вакансії за темою

Гарант-Інфо
4 дні тому

Middle PHP Developer (Laravel)

Middle PHP Developer для міжнародного B2B-продукту у телекомунікаціях. Розробка нового функціоналу на PHP 8.x/Laravel, підтримка кодової бази, робота з REST API, платіжними інтеграціями та MySQL. Вимоги: 2+ років комерційного досвіду PHP, впевнене знання Laravel, ООП, SOLID, тестування (PHPUnit/Pest), Git, Docker.

Alliance Digital
15 днів тому

PHP Developer

Middle PHP-розробник для фінтех-продукту. Розробка backend на Laravel з PostgreSQL, RabbitMQ, Redis. Реалізація складної бізнес-логіки кредитування, фінансових операцій, зовнішніх інтеграцій. Вимоги: 3+ років PHP, впевнена робота з Laravel, OOP/SOLID, складна бізнес-логіка, PostgreSQL, черги, тестування, production-mindset.

N-iX
31 день тому

Middle Market Research Analyst (#5741)

Senior PHP Engineer для консолідації двох legacy портальів в єдину сучасну платформу. Основний стек: PHP 8.x, Laravel, RabbitMQ, MySQL, Nuxt.js/Vue.js на AWS. Потрібні 5+ років досвіду з PHP, deep expertise в Laravel, event-driven архітектурі, AWS та SQL optimization. Роль передбачає дизайн високоякісного коду, архітектурні обговорення, роботу по всьому стеку та співпрацю з розподіленою командою в різних часових поясах.

Пакети за темою

Pest

pestphp/pest

Тестовий фреймворк з лаконічним синтаксисом поверх PHPUnit: тести описуються функціями замість класів. Має паралельний запуск, тести архітектури, покриття і мутаційне тестування.

11,667 v5.1.1 2

Bagisto

bagisto/bagisto

Bagisto — це платформа для електронної комерції, побудована на Laravel. Вона надає готове рішення для створення та управління інтернет-магазинами з підтримкою каталогу товарів, замовлень, платежів та клієнтів.

28,086 v2.5.0-beta1 13 25