Тестирование в PHP: обзор фреймворков и инструментов (PHPUnit, Pest, Codeception)

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Тестирование в PHP: фреймворки и инструменты

Качество кода — основа успешного веб-проекта. Для PHP-разработчиков тестирование перестало быть опцией и стало обязательным этапом разработки. В этой статье разберём три ключевых инструмента: PHPUnit (стандарт индустрии), Pest (современный минимализм) и Codeception (интеграционное тестирование). Вы узнаете, как писать unit-тесты, работать с mock-объектами и внедрять TDD в PHP-проекты.

1. PHPUnit — фундамент тестирования PHP

PHPUnit — де-факто стандарт для модульного тестирования PHP. Он входит в состав Symfony, Laravel и других популярных фреймворков.

Установка и базовый тест

composer require --dev phpunit/phpunit

Пример простого теста для класса калькулятора:

// src/Calculator.php
class Calculator {
    public function add($a, $b) {
        return $a + $b;
    }
}

// tests/CalculatorTest.php
use PHPUnit\Framework\TestCase;

class CalculatorTest extends TestCase {
    public function testAddition() {
        $calc = new Calculator();
        $this->assertEquals(4, $calc->add(2, 2));
    }
}

Работа с mock-объектами

PHPUnit предоставляет встроенный механизм для создания заглушек (mock):

public function testUserRepository() {
    $mockRepo = $this->createMock(UserRepository::class);
    $mockRepo->method('findById')
             ->willReturn(new User(1, 'Alice'));

    $service = new UserService($mockRepo);
    $result = $service->getUser(1);
    $this->assertEquals('Alice', $result->getName());
}

2. Pest — элегантный синтаксис для тестов

Pest — это обёртка над PHPUnit, предлагающая более лаконичный и читаемый синтаксис. Идеально подходит для проектов, где важна скорость написания тестов.

Установка и пример

composer require --dev pestphp/pest

Сравните с PHPUnit: тот же тест в Pest выглядит так:

// tests/CalculatorTest.php
it('calculates addition', function () {
    $calc = new Calculator();
    expect($calc->add(2, 2))->toBe(4);
});

Продвинутые возможности

  • Higher Order Tests — цепочки вызовов без вложенности
  • Architecture Testing — проверка структуры классов
  • Snapshot Testing — сравнение с эталонными данными

3. Codeception — для интеграционного и функционального тестирования

Codeception объединяет unit-, функциональные и приёмочные тесты в одном фреймворке. Поддерживает Selenium, Symfony, Laravel, Yii и даже WordPress.

Структура тестов

codecept generate:cest acceptance LoginCest

Пример функционального теста для Laravel:

// tests/functional/UserCest.php
class UserCest {
    public function testLogin(FunctionalTester $I) {
        $I->amOnPage('/login');
        $I->fillField('email', 'user@example.com');
        $I->fillField('password', 'secret');
        $I->click('Login');
        $I->see('Dashboard');
    }
}

4. Дополнительные инструменты

  • Mockery — гибкая библиотека для mock-объектов (альтернатива встроенным мокам PHPUnit)
  • PHPStan / Psalm — статический анализ, выявляющий ошибки до запуска тестов
  • Infection — мутационное тестирование: проверяет качество самих тестов
  • PHP CodeSniffer — контроль соответствия PSR-12

5. Практический пример: TDD для API-сервиса

Реализуем простой цикл TDD (Test-Driven Development) для сервиса заказов:

Шаг 1. Пишем тест

// tests/OrderServiceTest.php
public function testCreateOrderCalculatesTotal() {
    $orderService = new OrderService();
    $items = [
        ['price' => 100, 'quantity' => 2],
        ['price' => 50, 'quantity' => 1]
    ];
    $total = $orderService->calculateTotal($items);
    $this->assertEquals(250, $total);
}

Шаг 2. Реализуем минимальный код

// src/OrderService.php
class OrderService {
    public function calculateTotal(array $items): float {
        $total = 0;
        foreach ($items as $item                    

Рекомендаций