Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Y
yii2
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
PSDI Army
yii2
Commits
bbe33346
Commit
bbe33346
authored
Jan 17, 2014
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
finished fixture feature.
parent
18291c5b
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
261 additions
and
2 deletions
+261
-2
console-fixture.md
docs/guide/console-fixture.md
+1
-1
test-fixture.md
docs/guide/test-fixture.md
+152
-0
TestCase.php
extensions/codeception/TestCase.php
+47
-0
ActiveFixture.php
framework/test/ActiveFixture.php
+61
-1
No files found.
docs/guide/console-fixture.md
View file @
bbe33346
...
...
@@ -37,7 +37,7 @@ return [
];
```
This data will be loaded to the
`users`
, but before it will be loaded table
`users`
will be cleared: all data deleted, sequence reset
ed
.
This data will be loaded to the
`users`
, but before it will be loaded table
`users`
will be cleared: all data deleted, sequence reset.
Above fixture example was auto-generated by
`yii2-faker`
extension, read more about it in these
[
section
](
#auto-generating-fixtures
)
.
Applying fixtures
...
...
docs/guide/test-fixture.md
0 → 100644
View file @
bbe33346
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
)
...
```
extensions/codeception/TestCase.php
View file @
bbe33346
...
...
@@ -5,6 +5,10 @@ namespace yii\codeception;
use
Yii
;
use
yii\base\InvalidConfigException
;
use
Codeception\TestCase\Test
;
use
yii\base\UnknownMethodException
;
use
yii\base\UnknownPropertyException
;
use
yii\test\ActiveFixture
;
use
yii\test\FixtureTrait
;
/**
* TestCase is the base class for all codeception unit tests
...
...
@@ -14,6 +18,8 @@ use Codeception\TestCase\Test;
*/
class
TestCase
extends
Test
{
use
FixtureTrait
;
/**
* @var array|string the application configuration that will be used for creating an application instance for each test.
* You can use a string to represent the file path or path alias of a configuration file.
...
...
@@ -29,6 +35,7 @@ class TestCase extends Test
{
parent
::
setUp
();
$this
->
mockApplication
();
$this
->
loadFixtures
();
}
/**
...
...
@@ -36,11 +43,51 @@ class TestCase extends Test
*/
protected
function
tearDown
()
{
$this
->
unloadFixtures
();
$this
->
destroyApplication
();
parent
::
tearDown
();
}
/**
* Returns the value of an object property.
*
* Do not call this method directly as it is a PHP magic method that
* will be implicitly called when executing `$value = $object->property;`.
* @param string $name the property name
* @return mixed the property value
* @throws UnknownPropertyException if the property is not defined
*/
public
function
__get
(
$name
)
{
$fixture
=
$this
->
getFixture
(
$name
);
if
(
$fixture
!==
null
)
{
return
$fixture
;
}
else
{
throw
new
UnknownPropertyException
(
'Getting unknown property: '
.
get_class
(
$this
)
.
'::'
.
$name
);
}
}
/**
* Calls the named method which is not a class method.
*
* Do not call this method directly as it is a PHP magic method that
* will be implicitly called when an unknown method is being invoked.
* @param string $name the method name
* @param array $params method parameters
* @throws UnknownMethodException when calling unknown method
* @return mixed the method return value
*/
public
function
__call
(
$name
,
$params
)
{
$fixture
=
$this
->
getFixture
(
$name
);
if
(
$fixture
instanceof
ActiveFixture
)
{
return
$fixture
->
getModel
(
reset
(
$params
));
}
else
{
throw
new
UnknownMethodException
(
'Unknown method: '
.
get_class
(
$this
)
.
"::
$name
()"
);
}
}
/**
* Mocks up the application instance.
* @param array $config the configuration that should be used to generate the application instance.
* If null, [[appConfig]] will be used.
...
...
framework/test/ActiveFixture.php
View file @
bbe33346
...
...
@@ -24,7 +24,7 @@ use yii\db\TableSchema;
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class
ActiveFixture
extends
Fixture
class
ActiveFixture
extends
Fixture
implements
\IteratorAggregate
,
\ArrayAccess
,
\Countable
{
/**
* @inheritdoc
...
...
@@ -210,4 +210,64 @@ class ActiveFixture extends Fixture
$this
->
db
->
createCommand
()
->
resetSequence
(
$table
->
fullName
,
1
)
->
execute
();
}
}
/**
* Returns an iterator for traversing the cookies in the collection.
* This method is required by the SPL interface `IteratorAggregate`.
* It will be implicitly called when you use `foreach` to traverse the collection.
* @return \ArrayIterator an iterator for traversing the cookies in the collection.
*/
public
function
getIterator
()
{
return
new
\ArrayIterator
(
$this
->
rows
);
}
/**
* Returns the number of items in the session.
* This method is required by Countable interface.
* @return integer number of items in the session.
*/
public
function
count
()
{
return
count
(
$this
->
rows
);
}
/**
* This method is required by the interface ArrayAccess.
* @param mixed $offset the offset to check on
* @return boolean
*/
public
function
offsetExists
(
$offset
)
{
return
isset
(
$this
->
rows
[
$offset
]);
}
/**
* This method is required by the interface ArrayAccess.
* @param integer $offset the offset to retrieve element.
* @return mixed the element at the offset, null if no element is found at the offset
*/
public
function
offsetGet
(
$offset
)
{
return
isset
(
$this
->
rows
[
$offset
])
?
$this
->
rows
[
$offset
]
:
null
;
}
/**
* This method is required by the interface ArrayAccess.
* @param integer $offset the offset to set element
* @param mixed $item the element value
*/
public
function
offsetSet
(
$offset
,
$item
)
{
$this
->
rows
[
$offset
]
=
$item
;
}
/**
* This method is required by the interface ArrayAccess.
* @param mixed $offset the offset to unset element
*/
public
function
offsetUnset
(
$offset
)
{
unset
(
$this
->
rows
[
$offset
]);
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment