Вы когда-нибудь ловили себя на мысли, что после каждого изменения кода приходится вручную проверять кучу функций? Знакомо? Тогда эта статья для вас. Мы разберем, как автоматизировать проверку вашего Yii2-приложения с помощью PHPUnit — мощного инструмента для тестирования. Вы научитесь писать тесты, которые сэкономят вам часы отладки и нервы.

Digital-студия WNDER

Почему тесты — это не роскошь, а необходимость

Представьте, что вы строите дом. Можно, конечно, сразу заселиться, но без проверки фундамента и стен есть риск, что однажды всё рухнет. Так и в программировании: тесты — это ваша страховка. Они помогают:

  • Быстро находить ошибки после изменений.
  • Уверенно рефакторить код.
  • Документировать поведение системы.
  • Экономить время на ручном тестировании.

В Yii2 тестирование встроено на уровне фреймворка, и PHPUnit — основной инструмент. Давайте настроим его.

Установка и настройка PHPUnit в Yii2

Yii2 Advanced и Basic шаблоны уже включают поддержку тестов. Если вы используете Basic, проверьте наличие папки tests. Если её нет, создайте. Установите PHPUnit через Composer:

composer require --dev phpunit/phpunit

Теперь создайте файл конфигурации phpunit.xml в корне проекта. Пример для Basic шаблона:

<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="vendor/autoload.php" colors="true">
    <testsuites>
        <testsuite name="Unit Tests">
            <directory>tests/unit</directory>
        </testsuite>
        <testsuite name="Functional Tests">
            <directory>tests/functional</directory>
        </testsuite>
    </testsuites>
</phpunit>

Убедитесь, что автозагрузка работает. В composer.json добавьте секцию autoload для тестов:

"autoload-dev": {
    "psr-4": {
        "tests\\": "tests/"
    }
}

Выполните composer dump-autoload.

Пишем первый unit-тест

Unit-тесты проверяют отдельные классы и методы в изоляции. Допустим, у нас есть модель User с методом getFullName():

namespace app\models;

use yii\base\Model;

class User extends Model
{
    public $firstName;
    public $lastName;

    public function getFullName()
    {
        return $this->firstName . ' ' . $this->lastName;
    }
}

Создадим тест UserTest в папке tests/unit/models:

namespace tests\unit\models;

use app\models\User;
use PHPUnit\Framework\TestCase;

class UserTest extends TestCase
{
    public function testGetFullName()
    {
        $user = new User();
        $user->firstName = 'John';
        $user->lastName = 'Doe';

        $this->assertEquals('John Doe', $user->getFullName());
    }
}

Запустите тест командой ./vendor/bin/phpunit tests/unit/models/UserTest.php. Если всё правильно, увидите зелёный результат.

Правило: Названия тестовых методов должны быть описательными. Вместо testFullName() пишите testGetFullNameReturnsConcatenatedString() — так вы сразу поймёте, что проверяется.

Functional тесты: проверяем приложение целиком

Functional тесты имитируют действия пользователя: отправку форм, переходы по ссылкам. Yii2 предоставляет класс FunctionalTestCase, который расширяет возможности PHPUnit. Убедитесь, что установлен пакет yii2-codeception или используйте встроенный yii\test\FunctionalTestCase (требует настройки).

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

namespace tests\functional;

use yii\test\FunctionalTestCase;

class LoginCest extends FunctionalTestCase
{
    public function testLoginWithValidCredentials()
    {
        $this->amOnPage('site/login');
        $this->fillField('LoginForm[username]', 'admin');
        $this->fillField('LoginForm[password]', 'admin');
        $this->click('Login');
        $this->see('Logout');
    }
}

Для работы функциональных тестов нужно настроить конфигурацию приложения для тестового окружения. Обычно создают файл tests/_config/functional.php и указывают его в phpunit.xml через bootstrap.

Запуск: ./vendor/bin/phpunit tests/functional.

Фикстуры: готовим данные для тестов

Фикстуры — это предустановленные данные, которые загружаются в базу перед тестом. В Yii2 есть компонент yii\test\Fixture. Создадим фикстуру для пользователей:

namespace tests\fixtures;

use yii\test\Fixture;

class UserFixture extends Fixture
{
    public $dataFile = '@tests/_data/user.php';
    public $depends = [];
}

Файл tests/_data/user.php возвращает массив данных:

<?php
return [
    [
        'id' => 1,
        'username' => 'admin',
        'password_hash' => Yii::$app->security->generatePasswordHash('admin'),
        'email' => 'admin@example.com',
    ],
];

В тесте загружаем фикстуру:

public function fixtures()
{
    return [
        'user' => UserFixture::class,
    ];
}

Теперь в тесте можно обращаться к данным через $this->user.

Полезные советы и лайфхаки

  • Используйте setUp() и tearDown() для подготовки и очистки окружения.
  • Для тестирования БД применяйте транзакции: оберните тест в транзакцию и откатывайте после.
  • Не тестируйте фреймворк — сосредоточьтесь на своей логике.
  • Запускайте тесты перед каждым коммитом (можно настроить Git hooks).
Тип тестаЧто проверяетСкорость
UnitОтдельные классы и методыБыстро
FunctionalВзаимодействие с приложением через HTTPСредне
AcceptanceПолный сценарий пользователя в браузереМедленно
Лайфхак: Чтобы не запускать все тесты каждый раз, используйте фильтр по имени: ./vendor/bin/phpunit --filter testGetFullName.

Заключение

Тестирование в Yii2 с PHPUnit — это не так сложно, как кажется. Начните с малого: напишите пару unit-тестов для моделей, затем переходите к функциональным. Со временем вы оцените, насколько увереннее стал ваш код. Помните: тесты — это инвестиция в будущее вашего проекта.

Удачи в тестировании!

Студия WNDER