Фикстуры
Фикстуры являются важной частью тестирования. Их основная цель — подготовить окружение в фиксированном/известном состоянии, чтобы тесты были повторяемыми и выполнялись ожидаемым образом. Yii предоставляет фреймворк фикстур, который позволяет точно определять ваши фикстуры и легко их использовать.
Ключевым понятием в фреймворке фикстур Yii является так называемый объект фикстуры. Объект фикстуры представляет собой конкретный аспект тестовой среды и является экземпляром yii\test\Fixture или его дочернего класса. Например, вы можете использовать UserFixture для обеспечения того, чтобы таблица базы данных пользователей содержала фиксированный набор данных. Вы загружаете один или несколько объектов фикстуры перед запуском теста и выгружаете их при завершении.
Фикстура может зависеть от других фикстур, указанных через свойство yii\test\Fixture::$depends. Когда фикстура загружается, фикстуры, от которых она зависит, автоматически загружаются ДО фикстуры; а когда фикстура выгружается, зависимые фикстуры выгружаются ПОСЛЕ фикстуры.
Определение фикстуры
Для определения фикстуры создайте новый класс, расширяя yii\test\Fixture или yii\test\ActiveFixture. Первый лучше подходит для фикстур общего назначения, а второй имеет расширенные функции, специально разработанные для работы с базами данных и ActiveRecord.
Следующий код определяет фикстуру относительно User ActiveRecord и соответствующей таблицы пользователей.
<?php
namespace app\tests\fixtures;
use yii\test\ActiveFixture;
class UserFixture extends ActiveFixture
{
public $modelClass = 'app\models\User';
}
Подсказка: Каждая
ActiveFixtureпредназначена для подготовки таблицы базы данных для целей тестирования. Вы можете указать таблицу, установив свойство yii\test\ActiveFixture::$tableName или yii\test\ActiveFixture::$modelClass. Если последнее, имя таблицы будет взято изActiveRecordкласса, указанногоmodelClass.
Примечание: yii\test\ActiveFixture подходит только для баз данных SQL. Для баз данных NoSQL Yii предоставляет следующие
ActiveFixtureклассы:
- Mongo DB: yii\mongodb\ActiveFixture
- Elasticsearch: yii\elasticsearch\ActiveFixture (с версии 2.0.2)
Данные фикстуры для фикстуры ActiveFixture обычно предоставляются в файле, расположенном по адресу FixturePath/data/TableName.php, где FixturePath обозначает каталог, содержащий файл класса фикстуры, а TableName — имя таблицы, связанной с фикстурой. В приведенном выше примере файл должен быть @app/tests/fixtures/data/user.php. Файл данных должен возвращать массив строк данных, которые должны быть вставлены в таблицу пользователей. Например,
<?php
return [
'user1' => [
'username' => 'lmayert',
'email' => 'strosin.vernice@jerde.com',
'auth_key' => 'K3nF70it7tzNsHddEiq0BZ0i-OU8S3xV',
'password' => '$2y$13$WSyE5hHsG1rWN2jV8LRHzubilrCLI5Ev/iK0r3jRuwQEs2ldRu.a2',
],
'user2' => [
'username' => 'napoleon69',
'email' => 'aileen.barton@heaneyschumm.com',
'auth_key' => 'dZlXsVnIDgIzFgX4EduAqkEPuphhOh9q',
'password' => '$2y$13$kkgpvJ8lnjKo8RuoR30ay.RjDf15bMcHIF7Vz1zz/6viYG5xJExU6',
],
];
Вы можете присвоить псевдоним строке, чтобы позже в своем тесте вы могли обратиться к строке по псевдониму. В приведенном выше примере две строки имеют псевдонимы user1 и user2 соответственно.
Кроме того, вам не нужно указывать данные для столбцов с автоматическим увеличением. Yii автоматически заполнит фактические значения в строки при загрузке фикстуры.
Подсказка: Вы можете настроить расположение файла данных, установив свойство yii\test\ActiveFixture::$dataFile. Вы также можете переопределить yii\test\ActiveFixture::getData() для предоставления данных.
Как мы описали ранее, фикстура может зависеть от других фикстур. Например, UserProfileFixture может потребоваться зависеть от UserFixture, потому что таблица профилей пользователей содержит внешний ключ, указывающий на таблицу пользователей. Зависимость задается через свойство yii\test\Fixture::$depends, как показано ниже,
namespace app\tests\fixtures;
use yii\test\ActiveFixture;
class UserProfileFixture extends ActiveFixture
{
public $modelClass = 'app\models\UserProfile';
public $depends = ['app\tests\fixtures\UserFixture'];
}
Зависимость также гарантирует, что фикстуры загружаются и выгружаются в определенном порядке. В приведенном выше примере UserFixture всегда будет загружаться перед UserProfileFixture, чтобы гарантировать существование всех ссылок на внешний ключ, и выгружаться после того, как UserProfileFixture будет выгружено по той же причине.
В приведенном выше примере показано, как определить фикстуру относительно таблицы базы данных. Чтобы определить фикстуру, не связанную с базой данных (например, фикстуру относительно определенных файлов и каталогов), вы можете расширить базовый класс yii\test\Fixture и переопределить методы load() и unload().
Использование фикстур
Если вы используете Codeception для тестирования своего кода, вы должны рассмотреть возможность использования расширения yii2-codeception, которое имеет встроенную поддержку загрузки и доступа к фикстурам. Если вы используете другие фреймворки тестирования, вы можете использовать yii\test\FixtureTrait в своих тестовых случаях, чтобы достичь той же цели.
В следующем мы опишем, как написать тестовый класс UserProfile единичного теста с использованием yii2-codeception.
В вашем классе тестового единичного теста, расширяющем yii\codeception\DbTestCase или yii\codeception\TestCase, объявляйте, какие фикстуры вы хотите использовать в методе fixtures(). Например,
namespace app\tests\unit\models;
use yii\codeception\DbTestCase;
use app\tests\fixtures\UserProfileFixture;
class UserProfileTest extends DbTestCase
{
public function fixtures()
{
return [
'profiles' => UserProfileFixture::className(),
];
}
// ...test methods...
}
Фикстуры, перечисленные в методе fixtures(), будут автоматически загружаться перед запуском каждого метода теста в тестовом случае и выгружаться после завершения каждого метода теста. И, как мы описывали ранее, когда фикстура загружается, все ее зависимые фикстуры будут автоматически загружены предварительно. В приведенном выше примере, потому что UserProfileFixture зависит от UserFixture, при запуске любого метода теста в тестовом классе две фикстуры будут загружены последовательно: UserFixture и UserProfileFixture.
При указании фикстур в fixtures(), вы можете использовать либо имя класса, либо массив конфигурации для ссылки на фикстуру. Массив конфигурации позволит вам настроить свойства фикстуры при загрузке фикстуры.
Вы также можете назначить псевдоним фикстуре. В приведенном выше примере UserProfileFixture имеет псевдоним profiles. В методах тестов вы можете получить доступ к объекту фикстуры, используя его псевдоним. Например, $this->profiles вернет объект UserProfileFixture.
Поскольку UserProfileFixture расширяет ActiveFixture, вы можете далее использовать следующий синтаксис для доступа к данным, предоставленным фикстурой:
// returns the data row aliased as 'user1'
$row = $this->profiles['user1'];
// returns the UserProfile model corresponding to the data row aliased as 'user1'
$profile = $this->profiles('user1');
// traverse every data row in the fixture
foreach ($this->profiles as $row) ...
Информация:
$this->profilesпо-прежнему является объектом типаUserProfileFixture. Вышеперечисленные функции доступа реализованы с помощью магических методов PHP.
Определение и использование глобальных фикстур
Описанные выше фикстуры в основном используются отдельными тестовыми случаями. В большинстве случаев вам также нужны некоторые глобальные фикстуры, которые применяются ко ВСЕМ или многим тестовым случаям. Примером является yii\test\InitDbFixture, который выполняет две задачи:
- Выполняет некоторые общие задачи инициализации, выполняя скрипт, расположенный в
@app/tests/fixtures/initdb.php; - Отключает проверку целостности базы данных перед загрузкой других фикстур базы данных и снова включает ее после выгрузки других фикстур базы данных.
Использование глобальных фикстур аналогично использованию обычных фикстур. Единственное отличие состоит в том, что вы объявляете эти фикстуры в yii\codeception\TestCase::globalFixtures() вместо fixtures(). Когда тестовый случай загружает фикстуры, он сначала загружает глобальные фикстуры, а затем — обычные.
По умолчанию yii\codeception\DbTestCase уже объявляет InitDbFixture в методе globalFixtures(). Это означает, что вам нужно работать с @app/tests/fixtures/initdb.php, только если вы хотите выполнить некоторые задачи инициализации перед каждым тестом. В противном случае вы можете просто сосредоточиться на разработке каждого отдельного тестового случая и соответствующих фикстур.
Организация классов и файлов данных фикстур
По умолчанию классы фикстур ищут соответствующие файлы данных в папке data, которая является подпапкой каталога, содержащего файлы классов фикстур. Вы можете следовать этой согласованности при работе с простыми проектами. В больших проектах, скорее всего, вам часто потребуется использовать разные файлы данных для одного и того же класса фикстуры для разных тестов. Поэтому мы рекомендуем организовывать файлы данных иерархически, аналогично вашим пространствам имен классов. Например,
# under folder tests\unit\fixtures
data\
components\
fixture_data_file1.php
fixture_data_file2.php
...
fixture_data_fileN.php
models\
fixture_data_file1.php
fixture_data_file2.php
...
fixture_data_fileN.php
# and so on
Таким образом, вы избежите конфликтов файлов данных фикстур между тестами и будете использовать их по мере необходимости.
Примечание: В приведенном выше примере имена файлов фикстур указаны только для примера. В реальной жизни вы должны называть их в соответствии с тем, от какого класса фикстур ваши классы фикстур расширяются. Например, если вы расширяете yii\test\ActiveFixture для фикстур базы данных, вы должны использовать имена таблиц базы данных как имена файлов данных фикстуры; если вы расширяете yii\mongodb\ActiveFixture для фикстур MongoDB, вы должны использовать имена коллекций как имена файлов.
Аналогичная иерархия может использоваться для организации файлов классов фикстур. Вместо использования data в качестве корневого каталога, вы можете использовать fixtures в качестве корневого каталога, чтобы избежать конфликтов с файлами данных.
Резюме
Примечание: Этот раздел находится в стадии разработки.
В приведенном выше примере показано, как определять и использовать фикстуры. Ниже приводится типичный рабочий процесс выполнения тестов единиц, связанных с базой данных:
- Используйте инструмент
yii migrateдля обновления вашей тестовой базы данных до последней версии; - Запустите тестовый случай:
- Загрузить фикстуры: очистить соответствующие таблицы базы данных и заполнить их данными фикстур;
- Выполнить фактический тест;
- Выгрузить фикстуры.
- Повторите шаг 2 до тех пор, пока все тесты не завершатся.
Требуется доработка ниже
Управление фикстурами
Примечание: Этот раздел находится в разработке.
todo: этот учебник может быть объединен с вышеуказанной частью test-fixtures.md
Фикстуры являются важной частью тестирования. Их основное назначение — снабдить вас данными, необходимыми для тестирования различных случаев. Благодаря этим данным ваши тесты становятся более эффективными и полезными.
Yii поддерживает фикстуры через команду yii fixture командной строки. Этот инструмент поддерживает:
- Загрузку фикстур в различные хранилища, такие как: СУБД, NoSQL и т. д.;
- Выгрузку фикстур различными способами (обычно это очистка хранилища);
- Автоматическое создание фикстур и заполнение их случайными данными.
Формат фикстур
Фикстуры — это объекты с различными методами и конфигурациями. Обратитесь к официальной документации по ним. Предположим, у нас есть данные фикстур для загрузки:
#users.php file under fixtures data path, by default @tests\unit\fixtures\data
return [
[
'name' => 'Chase',
'login' => 'lmayert',
'email' => 'strosin.vernice@jerde.com',
'auth_key' => 'K3nF70it7tzNsHddEiq0BZ0i-OU8S3xV',
'password' => '$2y$13$WSyE5hHsG1rWN2jV8LRHzubilrCLI5Ev/iK0r3jRuwQEs2ldRu.a2',
],
[
'name' => 'Celestine',
'login' => 'napoleon69',
'email' => 'aileen.barton@heaneyschumm.com',
'auth_key' => 'dZlXsVnIDgIzFgX4EduAqkEPuphhOh9q',
'password' => '$2y$13$kkgpvJ8lnjKo8RuoR30ay.RjDf15bMcHIF7Vz1zz/6viYG5xJExU6',
],
];
Если мы используем фикстуру, которая загружает данные в базу данных, то эти строки будут применены к таблице users. Если мы используем фикстуру NoSQL, например, фикстуру mongodb, то эти данные будут применены к коллекции users mongodb. Чтобы узнать о реализации различных стратегий загрузки и многом другом, обратитесь к официальной документации. Приведенный выше пример фикстуры был сгенерирован расширением yii2-faker, подробнее об этом можно узнать в этом разделе. Имена классов фикстур не должны быть множественного числа.
Загрузка фикстур
Классы фикстур должны иметь суффикс Fixture класса. По умолчанию фикстуры будут искаться в пространстве имен tests\unit\fixtures, вы можете изменить это поведение с помощью конфигурации или параметров команды. Вы можете исключить некоторые фикстуры при загрузке или выгрузке, указав - перед их именем, например, -User.
Для загрузки фикстуры выполните следующую команду:
Примечание: Перед загрузкой данных выполняется последовательность выгрузки. Обычно это приводит к очистке всех существующих данных, вставленных предыдущими выполнениями фикстур.
yii fixture/load <fixture_name>
Необходимый параметр fixture_name указывает имя фикстуры, данные которой будут загружены. Вы можете загрузить несколько фикстур одновременно. Ниже приведены корректные форматы этой команды:
// load `User` fixture yii fixture/load User // same as above, because default action of "fixture" command is "load" yii fixture User // load several fixtures yii fixture "User, UserProfile" // load all fixtures yii fixture/load "*" // same as above yii fixture "*" // load all fixtures except ones yii fixture "*, -DoNotLoadThisOne" // load fixtures, but search them in different namespace. By default namespace is: tests\unit\fixtures. yii fixture User --namespace='alias\my\custom\namespace' // load global fixture `some\name\space\CustomFixture` before other fixtures will be loaded. // By default this option is set to `InitDbFixture` to disable/enable integrity checks. You can specify several // global fixtures separated by comma. yii fixture User --globalFixtures='some\name\space\Custom'
Выгрузка фикстур
Для выгрузки фикстуры выполните следующую команду:
// unload Users fixture, by default it will clear fixture storage (for example "users" table, or "users" collection if this is mongodb fixture). yii fixture/unload User // Unload several fixtures yii fixture/unload "User, UserProfile" // unload all fixtures yii fixture/unload "*" // unload all fixtures except ones yii fixture/unload "*, -DoNotUnloadThisOne"
К этой команде также можно применить те же параметры команды, что и: namespace, globalFixtures.
Глобальная настройка команды
Хотя параметры командной строки позволяют нам настраивать команду миграции в режиме реального времени, иногда мы можем захотеть настроить команду один раз для всех. Например, вы можете настроить другой путь миграции следующим образом:
'controllerMap' => [
'fixture' => [
'class' => 'yii\console\controllers\FixtureController',
'namespace' => 'myalias\some\custom\namespace',
'globalFixtures' => [
'some\name\space\Foo',
'other\name\space\Bar'
],
],
]
Автоматическое создание фикстур
Yii также может автоматически генерировать для вас фикстуры на основе шаблона. Вы можете создавать свои фикстуры с различными данными на разных языках и в разных форматах. Эта функция выполняется с помощью библиотеки Faker и расширения yii2-faker. Подробнее см. руководство расширения guide.
© 2008–2017 by Yii Software LLC
Licensed under the three clause BSD license.
http://www.yiiframework.com/doc-2.0/guide-test-fixtures.html