Немного о тестировании в Yii2

В данное время покрываю тестами проект-долгострой на Yii2. Возможно кому-то пригодятся заметки.

На официальном сайте Codeception хорошо описаны основы и модули для Yii2. Там можно найти исчерпывающее руководство по функционалу и настройкам.

В документации Yii2 упоминается устаревший пакет yiisoft/yii2-codeception. Он уже практически нигде не используется и с 2018 года помечен как «deprecated». Вместо него используется codeception/module-yii2.

Настройка

  1. Входной скрипт — /web/index-test.php
<?php
 
if (!in_array(@$_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1'])) {
    die('You are not allowed to access this file.');
}
 
require __DIR__ . '/../vendor/autoload.php';
 
(Dotenv\Dotenv::createImmutable(__DIR__ . DIRECTORY_SEPARATOR . '..'))->load();
 
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'test');
 
require __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';
 
(new yii\web\Application(
    require __DIR__ . '/../config/test.php'
))->run();

2. Конфигурация приложения — /config/test.php

 
<?php
 
return [
    // ...
    'components' => [
        'db' => [
            'class' => 'yii\db\Connection',
            'dsn' => 'mysql:host=' . env('MYSQL_TEST_HOST') . ';dbname=' . env('MYSQL_TEST_DATABASE'),
            'username' => env('MYSQL_TEST_USER'),
            'password' => env('MYSQL_TEST_PASSWORD'),
            'charset' => 'utf8',
        ],
    ],
    // ...
];

Для тестирования желательно создавать дополнительную базу данных или отдельный контейнер, если разработка происходит в окружении Докера.

3. Конфигурация приложения — /config/console.php

 
<?php
 
return [
    // ...
    'controllerMap' => [
        // ...
        'fixture' => [
            'class' => 'yii\faker\FixtureController',
        ],
        // ...
    ],
    // ...
];

4. Конфигурация запуска — /tests/_bootstrap.php

 
<?php
 
require __DIR__ .'/../vendor/autoload.php';
 
(Dotenv\Dotenv::createImmutable(__DIR__ . DIRECTORY_SEPARATOR . '..'))->load();
 
define('YII_ENV', 'test');
defined('YII_DEBUG') or define('YII_DEBUG', true);
 
require_once __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';

Настройки модульных, функциональных и приёмочных тестов также находятся в корне директории tests:

  • /test/functional.suite.yml
  • /test/unit.suite.yml
  • /test/acceptance.suite.yml.example (по умолчанию приёмочные тесты не включены и добавлен только пример конфигурации);

Эти файлы в дополнительной настройке для начала работы не нуждаются.

Основные команды

Первичная настройка:

vendor/bin/codecept bootstrap

По умолчанию в шаблонах приложений Yii2 эта команда уже выполнена.

Генерация модулей для тестов:

vendor/bin/codecept build

Они появится в /tests/_support/_generated

Запуск тестов:

vendor/bin/codecept run
 
vendor/bin/codecept run unit
vendor/bin/codecept run unit --steps
 
vendor/bin/codecept run functional
vendor/bin/codecept run functional --steps
 
php vendor/bin/codecept run --steps --xml --html

Генерация тестов:

vendor/bin/codecept generate:cest functional MyTest
vendor/bin/codecept generate:test unit MyTest

Фикстуры

За генерацию фикстур отвечает yii\faker\FixtureController. Основные настройки:

  • namespace — пространство имен по умолчанию;
  • globalFixtures — глобальные фикстуры;
  • templatePath — путь до директории шаблонов;
  • fixtureDataPath — путь до директории выходных данных;
  • language — язык на котором генерируются данные;
  • count — количество записей.

Эти настройки можно указать в конфигурации приложений или при вызове команд генерации фикстур через параметры.

Пример конфигурации:

 
<?php
 
return [
    // ...
    'controllerMap' => [
        // ...
        'fixture' => [
            'class' => 'yii\faker\FixtureController',
 
            'namespace' => 'app\tests\fixtures',
            'globalFixtures' => [
                'yii\test\InitDbFixture'
                // ...
            ],
 
            'templatePath' => '@tests/fixtures/templates',
            'fixtureDataPath' => '@tests/fixtures/data',
            'language' => 'ru_RU',
            'count' => 10,
        ],
        // ...
    ],
    // ...
];

Пример фикстуры /tests/fixtures/UserFixture.php

 
<?php
 
namespace app\tests\fixtures;
 
use yii\test\ActiveFixture;
 
class UserFixture extends ActiveFixture
{
    public $modelClass = 'app\models\User\User';
    public $dataFile = '@app/tests/fixtures/data/users.php';
}

Пример шаблона фикстуры /tests/fixtures/templates/users.php

 
<?php
 
/**
 * @var $faker \Faker\Generator
 */
 
use app\models\User\User;
 
return [
    'role' => User::ROLE_USER,
    'status' => $faker->randomElement([
        User::STATUS_NOT_ACTIVE,
        User::STATUS_ACTIVE,
        User::STATUS_LOCKED,
    ]),
    'email' => $faker->email,
    'password_hash' => Yii::$app->security->generatePasswordHash(123456),
    'created_at' => date('Y-m-d H:i:s'),
    'updated_at' => date('Y-m-d H:i:s'),
];

Генерация фикстур:

php yii fixture/generate users
php yii fixture/generate users --count=20
php yii fixture/generate users --count=20 --language=ru_RU
php yii fixture/generate users --templatePath=@tests/fixtures/templates
php yii fixture/generate users --fixtureDataPath=@tests/fixtures/data

Работать с фикстурами можно двумя способами, через консольные команды и код.

Консольные команды:

ВНИМАНИЕ! Перед работой с фикстурами для тестов перейдите в соответствующую директорию бинарников. Иначе будет затронута текущая база вместо тестовой.

cd /app/tests/bin
 
# загрузка данных в базу
php yii fixture User
php yii fixture/load User
php yii fixture/load "User, Product"
php yii fixture/load "*, -Product"
php yii fixture/load "*"
 
# удаление данных из базы
php yii fixture/unload User
php yii fixture/unload "User, Product"
php yii fixture/unload "*, -Product"
php yii fixture/unload "*"

Через код так:

 
<?php
 
namespace app\tests\unit\models;
 
use app\tests\fixtures\UserFixture;
 
class UserTest extends \Codeception\Test\Unit
{
    /**
     * @var \UnitTester
     */
    protected $tester;
 
    public function _fixtures()
    {
        return [
            'users' => [
                'class' => UserFixture::class,
                'dataFile' => '@app/tests/fixtures/data/random_users.php'
            ]
        ];
    }
}

Или так:

 
<?php
 
namespace app\tests\unit\models;
 
use app\tests\fixtures\UserFixture;
 
class UserTest extends \Codeception\Test\Unit
{
    /**
     * @var \UnitTester
     */
    protected $tester;
 
    public function testFirst()
    {
        // сразу все
        $this->tester->haveFixtures([
            'user' => [
                'class' => UserFixture::class,
                'dataFile' => '@app/tests/fixtures/data/random_users.php'
            ]
        ]);
 
        // или по одной
        $this->tester->haveRecord(User::class, [
            'role' => User::ROLE_USER,
            'status' => User::STATUS_ACTIVE,
            'email' => 'user2@test.com',
            'password_hash' => \Yii::$app->security->generatePasswordHash(123456),
            'created_at' => date('Y-m-d H:i:s'),
            'updated_at' => date('Y-m-d H:i:s'),
        ]);
    }
}

Все остальные примеры находятся в документации.

Полезные ссылки

30.11.2022

Категория(-и): Yii

# # #

Добавить комментарий