Krótko: PHPUnit to standardowe narzędzie do automatycznego testowania kodu PHP; Pest to bazujący na nim framework z krótszym zapisem. Aktualny jest PHPUnit 13 (od lutego 2026, od PHP 8.4), Pest występuje w wersji 5. Automatyczne testy nie zamykają luk bezpieczeństwa w samym PHP, ale czynią aktualizacje przewidywalnymi: po PHP2Shell i przed końcem wsparcia PHP 8.2 w dniu 31.12.2026 to rozstrzygająca zaleta.
Dlaczego testować kod PHP?
Dla zarządu korzyść można ująć w jednym zdaniu: testy czynią zmiany tańszymi i bezpieczniejszymi. Automatyczny test w kilka sekund sprawdza, czy funkcja nadal robi to, co powinna, na przykład czy koszyk dobrze liczy albo czy logowanie odrzuca błędne hasła. Bez testów sprawdza to człowiek ręcznie albo nikt.
Szczególnie wyraźnie różnica widać przy aktualizacjach. Gdy PHP trzeba szybko zaktualizować z powodu krytycznej luki, wielu operatorów się waha, bo obawia się błędów w sklepie lub portalu klienta. Z zestawem testów aktualizacja najpierw przechodzi w środowisku testowym, testy pokazują problemy, a potem następuje wdrożenie na żywo.
PHPUnit: standard testów w PHP
PHPUnit co roku w lutym wydaje nową wersję główną. Każda wersja wymaga minimalnej wersji PHP i przez około dwa lata otrzymuje poprawki błędów. Według phpunit.de obowiązuje:
| PHPUnit | Wydano | Wymagane PHP | Poprawki błędów do |
|---|---|---|---|
| 13 | 06.02.2026 | od PHP 8.4 | 04.02.2028 |
| 12 | 07.02.2025 | od PHP 8.3 | 05.02.2027 |
| 11 | 02.02.2024 | od PHP 8.2 | 06.02.2026 |
| 10 | 03.02.2023 | od PHP 8.1 | 07.02.2025 |
Tabela pokazuje praktyczną zależność: projekt, który nadal używa PHPUnit 10, zwykle działa też jeszcze na starej wersji PHP. Narzędzia testowe i wersję PHP należy podnosić razem. PHPUnit instaluje się zwykle przez Composera jako zależność deweloperską.
Pierwszy test z PHPUnit
Test to klasa dziedzicząca po PHPUnit\Framework\TestCase. Metody testowe są publiczne i zaczynają się od test, albo oznacza się je atrybutem #[Test]. Przykład sprawdza prostą funkcję do obliczania ceny:
<?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 dostarcza kilka przypadków dla tego samego testu. Według dokumentacji PHPUnit musi być publiczny i statyczny. Obliczenia wykonuje się w groszach (centach) jako liczba całkowita, aby nie powstawały błędy zaokrągleń związane z liczbami zmiennoprzecinkowymi. Zestaw uruchamia się za pomocą ./vendor/bin/phpunit, jeśli PHPUnit zainstalowano przez Composera.
Pest: ta sama baza, krótszy zapis
Według dokumentacji Pest jest zbudowany na PHPUnit. Testy pisze się jako funkcje z it() lub test(), a oczekiwania z expect(). Pest 5 wymaga PHP 8.4. Instalacja według dokumentacji:
composer remove phpunit/phpunit
composer require pestphp/pest --dev --with-all-dependencies
./vendor/bin/pest --init
Ten sam test w zapisie Pest:
<?php
it('berechnet den Bruttopreis zum Normalsatz', function () {
expect(bruttopreis(10000, 19))->toBe(11900);
});
Istniejące testy PHPUnit wtyczka pestphp/pest-plugin-drift w większości przekształca automatycznie. Jaki zapis wybierze zespół, to kwestia gustu; decydujące jest, aby testy uruchamiały się regularnie.
Które rodzaje testów mają sens
- Testy jednostkowe: sprawdzają pojedyncze funkcje i klasy bez bazy danych i sieci.
- Testy integracyjne: sprawdzają współdziałanie z bazą danych, systemem plików lub interfejsami.
- Testy funkcjonalne przez HTTP: wywołują strony i formularze tak, jak robi to przeglądarka.
- Testy regresji bezpieczeństwa: utrwalają naprawione błędy, na przykład to, że dane wyjściowe są maskowane za pomocą
htmlspecialchars()albo że logowanie kończy się niepowodzeniem po błędnym haśle. - Smoke testy po wdrożeniu: kilka szybkich kontroli, czy działająca strona odpowiada po aktualizacji.
Uzupełnieniem testów jest analiza statyczna z PHPStan i Psalm, która znajduje błędy bez wykonywania kodu.
Testy jako siatka bezpieczeństwa dla aktualizacji i PHP2Shell
PHP2Shell pokazało, jak krótki może być czas między publikacją a presją działania: ogłoszenie 20.10.2026, poprawki 21.10.2026, pomarańczowy poziom ostrzeżenia BSI (niemiecki Federalny Urząd ds. Bezpieczeństwa w Technice Informatycznej). Kto miał zestaw testów, mógł zainstalować PHP 8.4.27 lub 8.3.36 w środowisku testowym, uruchomić testy i tego samego dnia wdrożyć na żywo. Bez testów często zostawał wybór między nieprzetestowaną aktualizacją a otwartą luką.
Jeszcze większa jest korzyść przy zmianie wersji głównej. Dla PHP 8.1 i starszych nie ma już oficjalnych aktualizacji, a PHP 8.2 kończy się 31.12.2026, jak wyjaśnia strona PHP End-of-Life. Przebieg testów względem wersji docelowej wcześnie pokazuje, które przestarzałe funkcje trzeba zastąpić. Sensowny jest pipeline CI, który uruchamia testy względem kilku wersji PHP, a do tego rzut oka na Release Candidates, takie jak PHP 8.6.0, ale nigdy w produkcji.
Proszę napisać test do każdego naprawionego błędu bezpieczeństwa w Państwa aplikacji. W ten sposób upewniają się Państwo, że ten sam błąd nie wróci przy późniejszej zmianie.
Jak konkretnie pomaga PHP SOS?
Przy migracji z PHP 8.1 i starszych oraz przy bieżących aktualizacjach wspieramy w taki sposób:
- Ocena stanu obecnego: Jakie istnieją testy, jakie wersje PHP i PHPUnit działają, gdzie brakuje testów dla krytycznych procesów?
- Zapewnienie minimalnego pokrycia: Wspólnie z Państwa zespołem deweloperskim lub agencją zabezpieczamy testami logowanie, formularze i ścieżki zamówień.
- Testowanie aktualizacji: Nowe wersje PHP działają najpierw w środowisku testowym względem zestawu testów.
- Dokumentacja wyniku: Otrzymują Państwo wyniki testów i stany wersji jako dowód wykonania kroku poprawki lub migracji.
Częste pytania
Jakiej wersji PHPUnit potrzebuję?
To zależy od Państwa wersji PHP. PHPUnit 13 wymaga PHP 8.4, PHPUnit 12 wymaga PHP 8.3, a PHPUnit 11 wymaga PHP 8.2. Aktualna tabela znajduje się na phpunit.de w sekcji wspieranych wersji.
Czy Pest zastępuje PHPUnit?
Według własnej dokumentacji Pest jest zbudowany na PHPUnit i oferuje krótszy zapis. Istniejące testy PHPUnit można za pomocą wtyczki Drift w większości przekształcić automatycznie, niektóre trzeba poprawić ręcznie.
Czy testy pomagają przeciw lukom bezpieczeństwa w samym PHP?
Nie bezpośrednio. Luki takie jak PHP2Shell tkwią w interpreterze i są zamykane aktualizacją PHP. Testy sprawiają jednak, że mogą Państwo szybko zainstalować tę aktualizację, bez obawy przed niezauważonymi błędami w aplikacji.
Ile testów wystarczy?
Stałej liczby nie ma. Sensowne jest pokrycie najpierw ścieżek krytycznych dla biznesu: logowania, zamówień, formularzy i interfejsów. Potem pokrycie testami rośnie wraz z każdą zmianą i każdym naprawionym błędem.