Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама
Новини 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 охоплює решту опцій, включаючи словники та власні директорії зберігання.

10

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

Коментарі

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

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

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

Filament v5.10.0
Новини 12 жовтня 2026

Filament v5.10.0: сітка в rich editor, скелетони таблиць і десятки виправлень

Вийшов Filament v5.10.0: елементи керування сіткою в rich editor, допоміжний контент для віджетів-графіків, скелетони завантаження таблиць, submitOnCompletion() для OneTimeCodeInput та багато виправлень авторизації, доступності й стану.

18
Laravel AI SDK на практиці
Новини 09 жовтня 2026

Laravel AI SDK на практиці: агент, що стоїть за There There

Фрік Ван дер Гертен розповідає, як у Spatie побудували AI-шар хелпдеска There There на Laravel AI SDK: клас агента, інструменти з типізованою JSON-схемою та делегування роботи звичайним domain-діям.

16

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

Creator Systems
4 дні тому

Middle Full Stack Developer (Laravel, Vue.js)

Laravel Віддалено Full-time Middle ₴80,000 - ₴100,000

Розробник буде вести повний цикл розробки вебзастосунків: від проєктування архітектури до запуску нового функціоналу, включно з REST API, інтерфейсами, роботою з базами даних та інтеграціями. Основний стек - Laravel (PHP 8+) і Vue.js 3. Потрібні від 2-3 років комерційного досвіду, знання Eloquent, черг, подій і middleware, JavaScript ES6+, MySQL або PostgreSQL, PHPUnit, Pest або Vitest та Git.

Rank Explore
4 дні тому

Full-Stack Engineer (PHP)

Full-stack розробник, який відповідатиме за систему від архітектури до стабільності в продакшені. Основний стек: PHP 8+ та Laravel, MySQL, Redis, черги й REST API; також JavaScript ES6+. Потрібен досвід комерційної розробки від 5 років, глибоке знання MySQL та системного дизайну, вміння дебажити продакшен і строго рев'ювати код, згенерований AI-інструментами.

Backend Developer Middle

Розробник backend для web і мобільних застосунків. Основний стек: PHP, Laravel, WordPress. Очікується досвід роботи з REST API, базами даних (MySQL, PostgreSQL, MS SQL), інтеграціями зовнішніх сервісів, написанням тестів. Вимагається практичний досвід Laravel та впевнене знання PHP, ООП, SOLID, Git, Linux. Робота з командою над різноплановими проєктами.

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

Pest

pestphp/pest

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

11,667 v5.1.1 4

Kalimera

welldigit/kalimera

Interactive installer that scaffolds Laravel applications the Well Digit way.

v1.0.0 10