Текуща ситуация: PHP2Shell. Две критични уязвимости в PHP (CVSS 9,2) позволяват злонамерен код без вход. Корекции от 21.10.2026 г.Какво да направите сега →

Тестване на PHP код: PHPUnit и Pest

PHPUnit е стандартният инструмент за тестване на PHP, а Pest се надгражда върху него. Който има тестове, внедрява актуализациите за сигурност и смяната на версии по-бързо и с по-малък риск.

Актуалност 5 мин. четенеЗнания за PHP

Накратко: PHPUnit е стандартният инструмент за автоматично тестване на PHP код; Pest е framework, изграден върху него, с по-кратък запис. Актуална е PHPUnit 13 (от февруари 2026 г., от PHP 8.4), а Pest е във версия 5. Автоматичните тестове не затварят уязвимости в самия PHP, но правят актуализациите планируеми: след PHP2Shell и преди края на поддръжката на PHP 8.2 на 31.12.2026 г. това е решаващото предимство.

Защо да тестваме PHP код?

За ръководството ползата може да се събере в едно изречение: тестовете правят промените по-евтини и по-сигурни. Автоматичният тест проверява за секунди дали една функция още прави онова, което трябва, например дали количката смята правилно или дали входът отхвърля грешни пароли. Без тестове това проверява човек на ръка или никой.

Разликата е особено ясна при актуализациите. Когато PHP трябва да се актуализира спешно заради критична уязвимост, много оператори се колебаят, защото се страхуват от грешки в магазина или в клиентския портал. С тестов пакет актуализацията първо минава в тестова среда, тестовете показват проблемите и после се преминава в продукция.

PHPUnit: стандартът за тестове на PHP

PHPUnit излиза всяка година през февруари в нова основна версия. Всяка версия изисква минимална версия на PHP и получава около две години корекции на грешки. Според phpunit.de важи:

PHPUnit Издадена Изискване към PHP Корекции на грешки до
13 06.02.2026 г. от PHP 8.4 04.02.2028 г.
12 07.02.2025 г. от PHP 8.3 05.02.2027 г.
11 02.02.2024 г. от PHP 8.2 06.02.2026 г.
10 03.02.2023 г. от PHP 8.1 07.02.2025 г.

Таблицата показва практическа зависимост: проект, който още ползва PHPUnit 10, обикновено още работи и на стара версия на PHP. Инструментите за тестване и версията на PHP е добре да се повишават заедно. PHPUnit обикновено се инсталира през Composer като зависимост за разработка.

Първи тест с PHPUnit

Тестът е клас, който наследява PHPUnit\Framework\TestCase. Тестовите методи са публични и започват с test, или алтернативно се отбелязват с атрибута #[Test]. Примерът проверява проста функция за изчисляване на цена:

<?php declare(strict_types=1);

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

final class BruttopreisTest extends TestCase
{
    public static function preise(): array
    {
        return [
            'Normalsatz'   => [10000, 19, 11900],
            'Ermäßigt'     => [10000, 7, 10700],
            'Null bleibt Null' => [0, 19, 0],
        ];
    }

    #[DataProvider('preise')]
    public function testBruttopreisInCent(int $netto, int $satz, int $erwartet): void
    {
        $this->assertSame($erwartet, bruttopreis($netto, $satz));
    }
}

Data provider-ът подава няколко случая за един и същ тест. Според документацията на PHPUnit той трябва да е публичен и статичен. Изчислява се в цента като цяло число, за да не възникват грешки при закръгляване от числа с плаваща запетая. Пакетът се изпълнява с ./vendor/bin/phpunit, ако PHPUnit е инсталиран през Composer.

Pest: същата основа, по-кратък запис

Според документацията Pest е изграден върху PHPUnit. Тестовете се пишат като функции с it() или test(), а очакванията – с expect(). Pest 5 изисква PHP 8.4. Инсталирането според документацията:

composer remove phpunit/phpunit
composer require pestphp/pest --dev --with-all-dependencies
./vendor/bin/pest --init

Същият тест в записа на Pest:

<?php
it('berechnet den Bruttopreis zum Normalsatz', function () {
    expect(bruttopreis(10000, 19))->toBe(11900);
});

Съществуващите тестове на PHPUnit плъгинът pestphp/pest-plugin-drift преобразува в по-голямата част автоматично. Кой запис ще избере един екип, е въпрос на вкус; решаващо е тестовете да се изпълняват редовно.

Кои видове тестове са смислени

  1. Unit тестове: проверяват отделни функции и класове без база данни или мрежа.
  2. Интеграционни тестове: проверяват взаимодействието с база данни, файлова система или интерфейси.
  3. Функционални тестове през HTTP: извикват страници и формуляри, както го прави браузърът.
  4. Регресионни тестове за сигурност: фиксират отстранени грешки, например че изходът се екранира с htmlspecialchars() или че входът се проваля след грешна парола.
  5. Smoke тестове след внедряване: няколко бързи проверки дали живият сайт отговаря след актуализация.

В допълнение към тестовете статичният анализ с PHPStan и Psalm открива грешки, без да изпълнява кода.

Тестовете като мрежа за сигурност при актуализации и PHP2Shell

PHP2Shell показа колко кратко може да е времето между публикуването и необходимостта от действие: съобщение на 20.10.2026 г., пачове на 21.10.2026 г., ниво на предупреждение на BSI оранжево. Който имаше тестов пакет, можеше да внедри PHP 8.4.27 или 8.3.36 в тестова среда, да пусне тестовете и да премине в продукция в същия ден. Без тестове често оставаше изборът между непроверена актуализация и отворена уязвимост.

Ползата е още по-голяма при смяна на основната версия. За PHP 8.1 и по-стари вече няма официални актуализации, а PHP 8.2 приключва на 31.12.2026 г., както обяснява страницата PHP End of Life. Тестово изпълнение срещу целевата версия показва рано кои остарели функции трябва да се заменят. Разумен е CI конвейер, който пуска тестовете срещу няколко версии на PHP, а към това поглед към release candidate като PHP 8.6.0, но никога в продукция.

Съвет

Пишете тест за всяка отстранена грешка в сигурността във Вашето приложение. Така гарантирате, че същата грешка няма да се върне при по-късна промяна.

Как помага PHP SOS конкретно?

При миграцията от PHP 8.1 и по-стари и при текущите актуализации подпомагаме така:

  • Оценка на наличното: Какви тестове има, каква версия на PHP и PHPUnit работи, къде липсват тестове за критични процеси?
  • Създаване на минимално покритие: Заедно с Вашия екип за разработка или Вашата агенция обезпечаваме входа, формулярите и пътищата на поръчките с тестове.
  • Тестване на актуализациите: Новите версии на PHP първо работят в тестова среда срещу пакета.
  • Документиране на резултата: Получавате резултатите от тестовете и версиите като доказателство за стъпката на пача или на миграцията.

Често задавани въпроси

Каква версия на PHPUnit ми трябва?

Зависи от Вашата версия на PHP. PHPUnit 13 изисква PHP 8.4, PHPUnit 12 – PHP 8.3, а PHPUnit 11 – PHP 8.2. Актуалната таблица е на phpunit.de сред поддържаните версии.

Pest заместител на PHPUnit ли е?

Според собствената си документация Pest е изграден върху PHPUnit и предлага по-кратък запис. Съществуващите тестове на PHPUnit могат в по-голямата си част да се преобразуват автоматично с плъгина Drift, някои трябва да се коригират на ръка.

Помагат ли тестовете срещу уязвимости в самия PHP?

Не директно. Уязвимости като PHP2Shell се намират в интерпретатора и се затварят чрез актуализация на PHP. Тестовете обаче гарантират, че можете да внедрите тази актуализация бързо, без страх от незабелязани грешки в приложението.

Колко теста са достатъчни?

Твърд брой няма. Разумно е първо да се покрият критичните за бизнеса пътища: вход, поръчка, формуляри, интерфейси. След това тестовото покритие расте с всяка промяна и с всяка отстранена грешка.

Източници

Незабавен контакт

Всеки час има значение. Пишете ни сега.

Опишете накратко системата, версията на PHP и какво сте забелязали. Ние се свързваме с Вас, уточняваме ситуацията и работим отдалечено, докато инцидентът бъде приключен и документиран.

Незабавна помощ