Qiang Xue
11 years ago
4 changed files with 261 additions and 2 deletions
@ -0,0 +1,152 @@
|
||||
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) ... |
||||
``` |
Loading…
Reference in new issue