Почему тестирование PHP — это не страшно, а полезно?
Представьте: вы написали скрипт на PHP, он работает. Вы радуетесь. Через неделю нужно добавить новую функцию. Вы меняете пару строк — и вдруг всё ломается. Знакомо? Если да, то вам срочно нужно познакомиться с тестированием PHP. Это не магия, а просто набор инструментов, которые спасут ваш проект от хаоса.
Многие начинающие разработчики боятся тестов. Кажется, что это сложно, скучно и отнимает время. На самом деле, unit-тестирование PHP — это как страховка: вы платите немного сейчас, чтобы не потерять всё потом. В этой статье мы разберём, с чего начать тестирование PHP новичку, какие инструменты использовать и как написать первый тест, не сойдя с ума.
Что такое тестирование и зачем оно нужно?
Тестирование кода — это процесс проверки, что ваша программа делает именно то, что вы от неё ожидаете. Вместо того чтобы каждый раз вручную открывать браузер и кликать по ссылкам, вы пишете специальные скрипты (тесты), которые делают это за вас.
Основные плюсы:
- Уверенность в коде. Вы точно знаете, что после изменений ничего не сломается.
- Экономия времени. Автоматическая проверка работает быстрее ручной.
- Документация. Тесты показывают, как должен работать ваш код.
- Упрощение рефакторинга. Можно смело переписывать код, если тесты проходят.
Самый популярный инструмент для тестирования PHP — это PHPUnit. Он де-факто стандарт в мире PHP. Именно с ним мы и будем работать.
Установка PHPUnit: два простых способа
Прежде чем писать тесты, нужно установить PHPUnit. Есть два основных пути.
Способ 1: Composer (рекомендуется)
Если вы уже используете Composer (а вы должны, это менеджер зависимостей для PHP), то всё просто. Откройте терминал в корне вашего проекта и выполните:
composer require --dev phpunit/phpunit ^10
Флаг --dev означает, что PHPUnit будет установлен только для разработки, не попадёт на боевой сервер.
Способ 2: PHAR-архив
Если Composer не ваш вариант, можно скачать PHPUnit как один файл:
wget https://phar.phpunit.de/phpunit.phar
chmod +x phpunit.phar
sudo mv phpunit.phar /usr/local/bin/phpunit
После этого команда phpunit --version должна показать версию.
Первый тест: пишем и запускаем
Теперь самое интересное. Создадим простой класс и напишем для него тест. Допустим, у нас есть функция, которая складывает два числа.
Шаг 1. Код для тестирования
Создайте файл src/Calculator.php:
<?php
namespace App;
class Calculator
{
public function add(float $a, float $b): float
{
return $a + $b;
}
}
Шаг 2. Тест для этого класса
PHPUnit следует соглашению: тесты хранятся в директории tests/, а имя файла теста совпадает с именем класса с суффиксом Test. Создайте tests/CalculatorTest.php:
<?php
namespace Tests;
use App\Calculator;
use PHPUnit\Framework\TestCase;
class CalculatorTest extends TestCase
{
public function testAdd()
{
$calculator = new Calculator();
$result = $calculator->add(2, 3);
$this->assertEquals(5, $result);
}
}
Что здесь происходит?
- Мы наследуемся от
TestCase— базового класса PHPUnit. - Метод
testAdd— это наш тест. PHPUnit автоматически запускает все методы, начинающиеся сtest. $this->assertEquals()— это assert (утверждение). Он проверяет, что результат совпадает с ожидаемым.
Шаг 3. Запуск
В терминале выполните:
./vendor/bin/phpunit tests/CalculatorTest.php
Если всё ок, вы увидите зелёную точку и надпись OK (1 test, 1 assertion). Поздравляю, вы написали свой первый юнит-тест на PHP!
Основные assert-методы: что нужно знать
PHPUnit предоставляет много методов для проверок. Вот самые популярные:
assertEquals($expected, $actual)— проверяет равенство значений (с учётом типов).assertSame($expected, $actual)— строгое равенство (===).assertTrue($condition)— проверяет, что условие истинно.assertFalse($condition)— проверяет, что условие ложно.assertNull($variable)— проверяет на null.assertCount($expectedCount, $array)— проверяет количество элементов в массиве.assertInstanceOf($className, $object)— проверяет, является ли объект экземпляром класса.
Пример использования нескольких assert'ов:
public function testUserCreation()
{
$user = new User('John', 'john@example.com');
$this->assertInstanceOf(User::class, $user);
$this->assertSame('John', $user->getName());
$this->assertStringContainsString('@', $user->getEmail());
}
Структура теста: Arrange-Act-Assert
Хороший тест всегда строится по шаблону AAA (Arrange, Act, Assert):
- Arrange — подготовка данных (создание объектов, установка параметров).
- Act — выполнение тестируемого действия (вызов метода).
- Assert — проверка результата.
В нашем примере с калькулятором это выглядит так:
// Arrange
$calculator = new Calculator();
// Act
$result = $calculator->add(2, 3);
// Assert
$this->assertEquals(5, $result);
Соблюдение этой структуры делает тесты читаемыми и понятными для других разработчиков.
Тестирование исключений и ошибок
Иногда код должен выбрасывать исключения при неверных данных. Как это проверить? Используйте expectException():
public function testDivisionByZero()
{
$this->expectException(\DivisionByZeroError::class);
$calculator = new Calculator();
$calculator->divide(10, 0);
}
Также можно проверить сообщение ошибки:
$this->expectExceptionMessage('Division