Представьте, что вы написали сайт для интернет-магазина. Всё работает, клиенты довольны. Но вдруг — баг: корзина перестала считать скидку. Вы лезете в код, ищете час, два, а проблема в одной строчке. Знакомо? PHPUnit — это инструмент, который ловит такие ошибки до того, как они доберутся до пользователя. В этой статье я расскажу, как начать тестировать свой код без лишней головной боли.
Что такое PHPUnit и зачем он нужен?
PHPUnit — это фреймворк для модульного тестирования PHP-кода. Если проще: вы пишете маленькие проверки для каждой функции или метода. Эти проверки запускаются автоматически и говорят: «Всё ок» или «Тут ошибка». Это как автоинспектор для вашего кода: он проверяет, не нарушили ли вы правила.
Зачем это нужно? Допустим, вы добавили новую фичу — и сломали старую. Без тестов вы узнаете об этом только от пользователей. С тестами — сразу после запуска. Экономит нервы и время.
Установка и первый тест
Установить PHPUnit проще простого. Если у вас есть Composer (менеджер пакетов для PHP), выполните команду:
composer require --dev phpunit/phpunit
Теперь создайте файл теста. Пусть у нас есть простой класс-калькулятор:
<?php
class Calculator {
public function add($a, $b) {
return $a + $b;
}
}
Тест для него будет выглядеть так:
<?php
use PHPUnit\Framework\TestCase;
class CalculatorTest extends TestCase {
public function testAdd() {
$calc = new Calculator();
$result = $calc->add(2, 3);
$this->assertEquals(5, $result);
}
}
Запускаем тест:
vendor/bin/phpunit tests/CalculatorTest.php
Если всё верно, увидите зелёную точку. Если нет — красную букву F и сообщение об ошибке.
Основные assert-методы: таблица для быстрого старта
Assert — это проверка. Вы говорите: «Я ожидаю, что результат будет равен 5». Если нет — тест падает. Вот самые полезные assert-методы:
| Метод | Что проверяет | Пример |
|---|---|---|
| assertEquals | Равенство значений (с учётом типа) | $this->assertEquals(5, $result) |
| assertSame | Строгое равенство (===) | $this->assertSame(5, $result) |
| assertTrue | Значение true | $this->assertTrue($isValid) |
| assertFalse | Значение false | $this->assertFalse($hasError) |
| assertNull | Значение null | $this->assertNull($user) |
Тестирование исключений: когда код должен падать
Иногда мы ожидаем, что код выбросит исключение. Например, если передали неверные данные. PHPUnit умеет проверять и это:
<?php
public function testDivideByZero() {
$this->expectException(\InvalidArgumentException::class);
$calc = new Calculator();
$calc->divide(10, 0);
}
Если метод divide выбросит InvalidArgumentException — тест пройдёт. Если нет — упадёт. Удобно, правда?
Фикстуры: готовим данные для тестов
Часто для теста нужны одинаковые объекты или база данных. Чтобы не создавать их в каждом тесте, используйте фикстуры — методы setUp и tearDown. setUp запускается перед каждым тестом, tearDown — после.
<?php
class UserTest extends TestCase {
private $user;
protected function setUp(): void {
$this->user = new User('John', 'john@example.com');
}
public function testGetEmail() {
$this->assertEquals('john@example.com', $this->user->getEmail());
}
protected function tearDown(): void {
unset($this->user);
}
}
Это избавляет от дублирования кода и делает тесты чище.
Моки: как тестировать код, который зависит от внешних сервисов
Представьте, что ваш класс отправляет email через внешний API. Во время теста вы не хотите реально слать письма — это медленно и может привести к спаму. Тут помогают моки (mock-объекты). Они имитируют поведение настоящего объекта.
<?php
public function testSendWelcomeEmail() {
$mailer = $this->createMock(Mailer::class);
$mailer->expects($this->once())
->method('send')
->willReturn(true);
$service = new UserService($mailer);
$result = $service->registerUser('test@example.com');
$this->assertTrue($result);
}
Здесь мы говорим: «Ожидаем, что метод send будет вызван ровно один раз и вернёт true». Если в коде send вызовется дважды — тест упадёт.
Итоговое резюме: что в итоге
PHPUnit — это не страшно. Это просто набор правил и инструментов, которые делают ваш код надёжнее. Начните с малого: напишите тест для одной функции. Потом для класса. Потом для всего проекта. Со временем вы заметите, что багов стало меньше, а уверенности в коде — больше.
Главное — не пытайтесь покрыть тестами всё сразу. Тестируйте критичные куски: логику, расчёты, работу с БД. А мелочи — по мере сил. И помните: тесты пишутся не для галочки, а для вашего спокойствия.



