You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
153 lines
6.7 KiB
153 lines
6.7 KiB
11 years ago
|
Fixtures
|
||
|
========
|
||
|
|
||
|
Fixtures are important part of testing. Their main purpose is to set up the environment in a fixed/known state
|
||
|
so that your tests are repeatable and run in an expected way. Yii provides a fixture framework that allows
|
||
|
you to define your fixtures precisely and use them easily.
|
||
|
|
||
|
A key concept in the Yii fixture framework is the so-called *fixture objects*. A fixture object is an instance
|
||
|
of [[yii\test\Fixture]] or its child class. It represents a particular aspect of a test environment. For example,
|
||
|
you may define `UserFixture` to initialize the user database table with a set of known data. You load one or multiple
|
||
|
fixture objects before running a test and unload them when finishing.
|
||
|
|
||
|
A fixture may depend on other fixtures, specified via its [[yii\test\Fixture::depends]] property.
|
||
|
When a fixture is being loaded, the fixtures it depends on will be automatically loaded BEFORE the fixture;
|
||
|
and when the fixture is being unloaded, the dependent fixtures will be unloaded AFTER the fixture.
|
||
|
|
||
|
|
||
|
Defining a Fixture
|
||
|
------------------
|
||
|
|
||
|
To define a fixture, create a new class by extending [[yii\test\Fixture]] or [[yii\test\ActiveFixture]].
|
||
|
The former is best suited for general purpose fixtures, while the latter has enhanced features specifically
|
||
|
designed to work with database and ActiveRecord.
|
||
|
|
||
|
If you extend from [[yii\test\Fixture]], make sure you override the [[yii\test\Fixture::load()]] method
|
||
|
with your custom code of setting up the test environment (e.g. creating specific directories or files).
|
||
|
In the following, we will mainly describe how to define a database fixture by extending [[yii\test\ActiveFixture]].
|
||
|
|
||
|
Each `ActiveFixture` is about setting up the test data needed by a database table. You may specify the table
|
||
|
by setting either the [[yii\test\ActiveFixture::tableName]] property or the [[yii\test\ActiveFixture::modelClass]]
|
||
|
property. The latter takes the name of an `ActiveRecord` class whose associated table will be used by the fixture.
|
||
|
|
||
|
```php
|
||
|
namespace app\tests\fixtures;
|
||
|
|
||
|
use yii\test\ActiveFixture;
|
||
|
|
||
|
class UserFixture extends ActiveFixture
|
||
|
{
|
||
|
public $modelClass = 'app\models\User';
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Next, you should provide the data needed by the user table in a file. By default, the file should be located at
|
||
|
`FixturePath/data/TableName.php`, where `FixturePath` stands for the directory containing the fixture class file,
|
||
|
and `TableName` is the name of the table associated with the fixture. In the example above, the file should be
|
||
|
`@app/tests/fixtures/data/tbl_user.php`, assuming the table associated with `User` is `tbl_user`.
|
||
|
|
||
|
The data file should return an array of data rows to be inserted into the user table. For example,
|
||
|
|
||
|
```php
|
||
|
<?php
|
||
|
return [
|
||
|
'user1' => [
|
||
|
'name' => 'Chase',
|
||
|
'login' => 'lmayert',
|
||
|
'email' => 'strosin.vernice@jerde.com',
|
||
|
'auth_key' => 'K3nF70it7tzNsHddEiq0BZ0i-OU8S3xV',
|
||
|
'password' => '$2y$13$WSyE5hHsG1rWN2jV8LRHzubilrCLI5Ev/iK0r3jRuwQEs2ldRu.a2',
|
||
|
],
|
||
|
'user2' => [
|
||
|
'name' => 'Celestine',
|
||
|
'login' => 'napoleon69',
|
||
|
'email' => 'aileen.barton@heaneyschumm.com',
|
||
|
'auth_key' => 'dZlXsVnIDgIzFgX4EduAqkEPuphhOh9q',
|
||
|
'password' => '$2y$13$kkgpvJ8lnjKo8RuoR30ay.RjDf15bMcHIF7Vz1zz/6viYG5xJExU6',
|
||
|
],
|
||
|
];
|
||
|
```
|
||
|
|
||
|
You may give an alias to a row so that later in your test, you may refer to the row via the alias. In the above example,
|
||
|
the two rows are aliased as `user1` and `user2`, respectively.
|
||
|
|
||
|
Also, you do not need to specify the data for auto-incremental columns. Yii will automatically fill the actual
|
||
|
values into the rows when the fixture is being loaded.
|
||
|
|
||
|
> Info: You may customize the location of the data file by setting the [[yii\test\ActiveFixture::dataFile]] property.
|
||
|
> If you set this property to be false, or if you do not provide the data file, the fixture will not load any data
|
||
|
> into the user table.
|
||
|
|
||
|
As we described earlier, a fixture may depend on other fixtures. For example, `UserProfileFixture` depends on `UserFixture`.
|
||
|
The dependency is specified via the [[yii\test\Fixture::depends]] property, like the following,
|
||
|
|
||
|
```php
|
||
|
namespace app\tests\fixtures;
|
||
|
|
||
|
use yii\test\ActiveFixture;
|
||
|
|
||
|
class UserProfileFixture extends ActiveFixture
|
||
|
{
|
||
|
public $modelClass = 'app\models\UserProfile';
|
||
|
public $depends = ['yii\test\DbFixture', 'app\tests\fixtures\UserFixture'];
|
||
|
}
|
||
|
```
|
||
|
|
||
|
Note that in the above, besides `app\tests\fixtures\UserFixture`, the dependency of `UserProfileFixture` also includes
|
||
|
`yii\test\DbFixture`. This is required by all `ActiveFixture` classes which set `yii\test\DbFixture` as the default value
|
||
|
of the `depends` property. The `DbFixture` class is responsible for toggling database integrity check and executing
|
||
|
an initialization script. Without `DbFixture`, you may not be able to freely inserting or deleting rows in a table
|
||
|
due to various DB constraints.
|
||
|
|
||
|
|
||
|
Using Fixtures
|
||
|
--------------
|
||
|
|
||
|
Yii provides [[yii\test\FixtureTrait]] which can be plugged into your test classes to let you easily load and access
|
||
|
fixtures. More often you would develop your test cases by using the `yii2-codeception` extension
|
||
|
which has the built-in support for the loading and accessing fixtures. In the following we will describe how to do so.
|
||
|
|
||
|
In your test case class extending [[yii\codeception\TestCase]], you declare which fixtures you want to use
|
||
|
in the [[yii\testFixtureTrait::fixtures()|fixtures()]] method. For example,
|
||
|
|
||
|
```php
|
||
|
namespace app\tests\unit\models;
|
||
|
|
||
|
use yii\codeception\TestCase;
|
||
|
use app\tests\fixtures\UserProfileFixture;
|
||
|
|
||
|
class UserProfileTest extends TestCase
|
||
|
{
|
||
|
public function fixtures()
|
||
|
{
|
||
|
return [
|
||
|
'profiles' => UserProfileFixture::className(),
|
||
|
];
|
||
|
}
|
||
|
|
||
|
// ...test methods...
|
||
|
}
|
||
|
```
|
||
|
|
||
|
The fixtures listed in the `fixtures()` method will be automatically loaded before running every test method
|
||
|
in the test case and unloaded after finishing every test method. And as we described before, when a fixture is
|
||
|
being loaded, all its dependent fixtures will be automatically loaded first. In the above example, because
|
||
|
`UserProfileFixture` depends on `UserFixture` and `DbFixture`, when running any test method in the test class,
|
||
|
three fixtures will be loaded sequentially: `DbFixture`, `UserFixture` and `UserProfileFixture`.
|
||
|
|
||
|
When declaring a fixture in a test class, you may assign an alias to a fixture. For example, `UserProfileFixture`
|
||
|
is aliased as `profiles` in the above. In the test methods, you may then access a fixture object using its alias.
|
||
|
For example, `$this->profiles` will return the `UserProfileFixture` object.
|
||
|
|
||
|
Because `UserProfileFixture` extends from `ActiveFixture`, you may further use the following syntax to access
|
||
|
the data provided by the fixture:
|
||
|
|
||
|
```php
|
||
|
// 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) ...
|
||
|
```
|