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
b496a04f
Commit
b496a04f
authored
Jan 19, 2014
by
Qiang Xue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactored fixture feature.
parent
12eca516
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
104 additions
and
766 deletions
+104
-766
console.php
apps/basic/config/console.php
+0
-4
_config.php
apps/basic/tests/unit/_config.php
+0
-4
test-fixture.md
docs/guide/test-fixture.md
+42
-48
CHANGELOG.md
framework/CHANGELOG.md
+0
-1
classes.php
framework/classes.php
+0
-1
FixtureController.php
framework/console/controllers/FixtureController.php
+1
-2
ActiveFixture.php
framework/test/ActiveFixture.php
+44
-53
BaseActiveFixture.php
framework/test/BaseActiveFixture.php
+1
-43
DbFixture.php
framework/test/DbFixture.php
+1
-253
DbFixtureManager.php
framework/test/DbFixtureManager.php
+0
-218
DbTestTrait.php
framework/test/DbTestTrait.php
+0
-113
InitDbFixture.php
framework/test/InitDbFixture.php
+11
-0
ActiveFixtureTest.php
tests/unit/framework/test/ActiveFixtureTest.php
+4
-26
tbl_customer.php
tests/unit/framework/test/data/tbl_customer.php
+0
-0
No files found.
apps/basic/config/console.php
View file @
b496a04f
...
...
@@ -25,10 +25,6 @@ return [
],
],
'db'
=>
$db
,
'fixture'
=>
[
'class'
=>
'yii\test\DbFixtureManager'
,
'basePath'
=>
'@tests/unit/fixtures'
,
],
],
'params'
=>
$params
,
];
apps/basic/tests/unit/_config.php
View file @
b496a04f
...
...
@@ -5,10 +5,6 @@ return yii\helpers\ArrayHelper::merge(
require
(
__DIR__
.
'/../_config.php'
),
[
'components'
=>
[
'fixture'
=>
[
'class'
=>
'yii\test\DbFixtureManager'
,
'basePath'
=>
'@tests/unit/fixtures'
,
],
'db'
=>
[
'dsn'
=>
'mysql:host=localhost;dbname=yii2_basic_unit'
,
],
...
...
docs/guide/test-fixture.md
View file @
b496a04f
...
...
@@ -5,9 +5,9 @@ Fixtures are important part of testing. Their main purpose is to set up the envi
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 create the user table and populate it with some known
data. You load one or multiple
A key concept in the Yii fixture framework is the so-called
*fixture objects*
. A fixture object
represents
a particular aspect of a test environment and is an instance of
[
[yii\test\Fixture
]
] or its child class
. For example,
you may
use
`UserFixture`
to make sure the user DB table contains a fixed set of
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.
...
...
@@ -22,13 +22,7 @@ To define a fixture, create a new class by extending [[yii\test\Fixture]] or [[y
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
]
], you should normally 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 preparing a DB table for testing purpose. You may specify the table
by setting either the
[
[yii\test\ActiveFixture::tableName
]
] property or the
[
[yii\test\ActiveFixture::modelClass
]
]
property. If the latter, the table name will be taken from the
`ActiveRecord`
class specified by
`modelClass`
.
The following code defines a fixture about the
`User`
ActiveRecord and the corresponding user table.
```
php
<?php
...
...
@@ -42,33 +36,12 @@ class UserFixture extends ActiveFixture
}
```
Next, you should override
[
[yii\test\ActiveFixture::loadSchema()
]
] to create the table. You may wonder why we need
to create the table when loading a fixture and why we do not work with a database which already has the table. This
is because preparing a complete test database is often very time consuming and in most test cases, only a very tiny part
of the database is touched. So the idea here is to create the table only when it is needed by the test.
> Tip: Each `ActiveFixture` is about preparing a DB table for testing purpose. You may specify the table
> by setting either the [[yii\test\ActiveFixture::tableName]] property or the [[yii\test\ActiveFixture::modelClass]]
> property. If the latter, the table name will be taken from the `ActiveRecord` class specified by `modelClass`.
```
php
<?php
namespace
app\tests\fixtures
;
use
yii\test\ActiveFixture
;
class
UserFixture
extends
ActiveFixture
{
public
$modelClass
=
'app\models\User'
;
protected
function
loadSchema
()
{
$this
->
createTable
(
'tbl_user'
,
[
'username'
=>
'string not null'
,
'email'
=>
'string not null'
,
...
]);
}
}
```
Lastly, you should provide the fixture data in a file located at
`FixturePath/data/TableName.php`
,
The fixture data for an
`ActiveFixture`
fixture is usually provided in a file 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`
. The data file should return an array of data rows
...
...
@@ -115,20 +88,25 @@ class UserProfileFixture extends ActiveFixture
public
$modelClass
=
'app\models\UserProfile'
;
public
$depends
=
[
'app\tests\fixtures\UserFixture'
];
}
```
In
the
above
,
we
have
shown
how
to
define
a
fixture
about
a
DB
table
.
To
define
a
fixture
not
related
with
DB
(
e
.
g
.
a
fixture
about
certain
files
and
directories
),
you
may
extend
from
the
more
general
base
class
[[
yii\test\Fixture
]]
and
override
the
[[
yii\test\Fixture
::
load
()
|
load
()]]
and
[[
yii\test\Fixture
::
unload
()
|
unload
()]]
methods
.
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 uses
[
[yii\test\FixtureTrait
]
] and has the built-in support for the loading and accessing fixtures.
If
you
are
using
[
CodeCeption
](
http
://
codeception
.
com
/
)
to
test
your
code
,
you
should
consider
using
the
`yii2-codeception`
extension
which
has
the
built
-
in
support
for
loading
and
accessing
fixtures
.
If
you
are
using
other
testing
frameworks
,
you
may
use
[[
yii\test\FixtureTrait
]]
in
your
test
cases
to
achieve
the
same
goal
.
In
the
following
we
will
describe
how
to
write
a
`UserProfile`
unit
test
class
using
`yii2-codeception`
.
In your unit test class extending
[
[yii\codeception\DbTestCase
]
] (or
[
[yii\codeception\TestCase
]
] if you are NOT
testing DB-related features), declare which fixtures you want to use in the
[
[yii\testFixtureTrait::fixtures()|fixtures()
]
] method.
For example,
In
your
unit
test
class
extending
[[
yii\codeception\DbTestCase
]]
or
[[
yii\codeception\TestCase
]],
declare
which
fixtures
you
want
to
use
in
the
[[
yii\testFixtureTrait
::
fixtures
()
|
fixtures
()]]
method
.
For
example
,
```
php
namespace app
\t
ests
\u
nit
\m
odels;
...
...
@@ -182,15 +160,31 @@ Defining and Using Global Fixtures
----------------------------------
The fixtures described above are mainly used by individual test cases. In most cases, you also need some global
fixtures that are applied to ALL or many test cases. An example is
[
[yii\test\InitDbFixture
]
] which is used to
set up a skeleton test database and toggle database integrity checks when applying other DB fixtures.
This fixture will try to execute a script located at
`@app/tests/fixtures/initdb.php`
. In this script, you may,
for example, load a basic DB dump containing the minimal set of tables, etc.
fixtures that are applied to ALL or many test cases. An example is
[
[yii\test\InitDbFixture
]
] which does
two things:
*
Perform some common initialization tasks by executing a script located at
`@app/tests/fixtures/initdb.php`
;
*
Disable the database integrity check before loading other DB fixtures, and re-enable it after other DB fixtures are unloead.
Using global fixtures is similar to using non-global ones. The only difference is that you declare these fixtures
in
[
[yii\codeception\TestCase::globalFixtures()
]
] instead of
`fixtures()`
. When a test case loads fixtures, it will
first load global fixtures and then non-global ones.
By default,
[
[yii\codeception\DbTestCase
]
] already declares
`InitDbFixture`
in its
`globalFixtures()`
method.
This means you only need to work with
`@app/tests/fixtures/initdb.php`
to set up your skeleton test database,
and you can then focus on developing each individual test case and the corresponding fixtures.
This means you only need to work with
`@app/tests/fixtures/initdb.php`
if you want to do some initialization work
before each test. You may otherwise simply focus on developing each individual test case and the corresponding fixtures.
Summary
-------
In the above, we have described how to define and use fixtures. Below we summarize the typical workflow
of running unit tests related with DB:
1.
Use
`yii migrate`
tool to upgrade your test database to the latest version;
2.
Run a test case:
-
Load fixtures: clean up the relevant DB tables and populate them with fixture data;
-
Perform the actual test;
-
Unload fixtures.
3.
Repeat 2 until all tests finish.
framework/CHANGELOG.md
View file @
b496a04f
...
...
@@ -21,7 +21,6 @@ Yii Framework 2 Change Log
-
Bug #1686: ActiveForm is creating duplicated messages in error summary (qiangxue)
-
Bug #1704: Incorrect regexp is used in
`Inflector::camelize()`
(qiangxue)
-
Bug #1710: OpenId auth client does not request required attributes correctly (klimov-paul)
-
Bug #1733: Incorrect code about
`$_modelClasses`
in
`DbFixtureManager`
(qiangxue)
-
Bug #1798: Fixed label attributes for array fields (zhuravljov)
-
Bug #1800: Better check for
`$_SERVER['HTTPS']`
in
`yii\web\Request::getIsSecureConnection()`
(ginus, samdark)
-
Bug #1827: Debugger toolbar is loaded twice if an action is calling
`run()`
to execute another action (qiangxue)
...
...
framework/classes.php
View file @
b496a04f
...
...
@@ -174,7 +174,6 @@ return [
'yii\rbac\Manager'
=>
YII_PATH
.
'/rbac/Manager.php'
,
'yii\rbac\PhpManager'
=>
YII_PATH
.
'/rbac/PhpManager.php'
,
'yii\requirements\YiiRequirementChecker'
=>
YII_PATH
.
'/requirements/YiiRequirementChecker.php'
,
'yii\test\DbFixtureManager'
=>
YII_PATH
.
'/test/DbFixtureManager.php'
,
'yii\test\DbTestTrait'
=>
YII_PATH
.
'/test/DbTestTrait.php'
,
'yii\validators\BooleanValidator'
=>
YII_PATH
.
'/validators/BooleanValidator.php'
,
'yii\validators\CompareValidator'
=>
YII_PATH
.
'/validators/CompareValidator.php'
,
...
...
framework/console/controllers/FixtureController.php
View file @
b496a04f
...
...
@@ -11,7 +11,6 @@ use Yii;
use
yii\console\Controller
;
use
yii\console\Exception
;
use
yii\helpers\FileHelper
;
use
yii\test\DbTestTrait
;
use
yii\helpers\Console
;
/**
...
...
@@ -309,7 +308,7 @@ class FixtureController extends Controller
/**
* @param array $fixtures
* @return array Array of found fixtures. These may differ
er
from input parameter as not all fixtures may exists.
* @return array Array of found fixtures. These may differ from input parameter as not all fixtures may exists.
*/
private
function
findFixtures
(
array
$fixtures
)
{
...
...
framework/test/ActiveFixture.php
View file @
b496a04f
...
...
@@ -15,13 +15,11 @@ use yii\db\TableSchema;
/**
* ActiveFixture represents a fixture backed up by a [[modelClass|ActiveRecord class]] or a [[tableName|database table]].
*
* Either [[modelClass]] or [[tableName]] must be set. And you should normally override [[loadSchema()]]
* to set up the necessary database schema (e.g. creating the table, view, trigger, etc.)
* You should also provide fixture data in the file specified by [[dataFile]] or overriding [[loadData()]] if you want
* to use code to generate the fixture data.
* Either [[modelClass]] or [[tableName]] must be set. You should also provide fixture data in the file
* specified by [[dataFile]] or overriding [[getData()]] if you want to use code to generate the fixture data.
*
* When the fixture is being loaded, it will first call [[
loadSchema()]] to initialize the database schema
.
* It will then
call [[loadData()]] to populate the table with the fixture data
.
* When the fixture is being loaded, it will first call [[
resetTable()]] to remove any existing data in the table
.
* It will then
populate the table with the data returned by [[getData()]]
.
*
* After the fixture is loaded, you can access the loaded data via the [[data]] property. If you set [[modelClass]],
* you will also be able to retrieve an instance of [[modelClass]] with the populated data via [[getModel()]].
...
...
@@ -38,22 +36,13 @@ class ActiveFixture extends BaseActiveFixture
*/
public
$tableName
;
/**
* @var string the file path or path alias of the data file that contains the fixture data
*
and will be loaded by [[load
Data()]]. If this is not set, it will default to `FixturePath/data/TableName.php`,
* @var string
|boolean
the file path or path alias of the data file that contains the fixture data
*
to be returned by [[get
Data()]]. If this is not set, it will default to `FixturePath/data/TableName.php`,
* where `FixturePath` stands for the directory containing this fixture class, and `TableName` stands for the
* name of the table associated with this fixture.
* name of the table associated with this fixture.
You can set this property to be false to prevent loading any data.
*/
public
$dataFile
;
/**
* @var boolean whether to reset the table associated with this fixture.
* By setting this property to be true, when [[loadData()]] is called, all existing data in the table
* will be removed and the sequence number (if any) will be reset.
*
* Note that you normally do not need to reset the table if you implement [[loadSchema()]] because
* there will be no existing data.
*/
public
$resetTable
=
false
;
/**
* @var TableSchema the table schema for the table associated with this fixture
*/
private
$_table
;
...
...
@@ -70,42 +59,20 @@ class ActiveFixture extends BaseActiveFixture
}
/**
* @return TableSchema the schema information of the database table associated with this fixture.
* @throws \yii\base\InvalidConfigException if the table does not exist
* Loads the fixture.
*
* The default implementation will first clean up the table by calling [[resetTable()]].
* It will then populate the table with the data returned by [[getData()]].
*
* If you override this method, you should consider calling the parent implementation
* so that the data returned by [[getData()]] can be populated into the table.
*/
public
function
getTableSchema
()
public
function
load
()
{
if
(
$this
->
_table
!==
null
)
{
return
$this
->
_table
;
}
$db
=
$this
->
db
;
$tableName
=
$this
->
tableName
;
if
(
$tableName
===
null
)
{
/** @var \yii\db\ActiveRecord $modelClass */
$modelClass
=
$this
->
modelClass
;
$tableName
=
$modelClass
::
tableName
();
}
$this
->
_table
=
$db
->
getSchema
()
->
getTableSchema
(
$tableName
);
if
(
$this
->
_table
===
null
)
{
throw
new
InvalidConfigException
(
"Table does not exist:
{
$tableName
}
"
);
}
return
$this
->
_table
;
}
$this
->
resetTable
();
/**
* Loads the fixture data.
* The default implementation will first reset the DB table and then populate it with the data
* returned by [[getData()]].
*/
protected
function
loadData
()
{
$table
=
$this
->
getTableSchema
();
if
(
$this
->
resetTable
)
{
$this
->
resetTable
();
}
foreach
(
$this
->
getData
()
as
$alias
=>
$row
)
{
$this
->
db
->
createCommand
()
->
insert
(
$table
->
fullName
,
$row
)
->
execute
();
if
(
$table
->
sequenceName
!==
null
)
{
...
...
@@ -123,8 +90,6 @@ class ActiveFixture extends BaseActiveFixture
/**
* Returns the fixture data.
*
* This method is called by [[loadData()]] to get the needed fixture data.
*
* The default implementation will try to return the fixture data by including the external file specified by [[dataFile]].
* The file should return an array of data rows (column name => column value), each corresponding to a row in the table.
*
...
...
@@ -147,7 +112,7 @@ class ActiveFixture extends BaseActiveFixture
}
/**
* Removes all existing data from the specified table and resets sequence number
if any
.
* Removes all existing data from the specified table and resets sequence number
to 1 (if any)
.
* This method is called before populating fixture data into the table associated with this fixture.
*/
protected
function
resetTable
()
...
...
@@ -158,4 +123,30 @@ class ActiveFixture extends BaseActiveFixture
$this
->
db
->
createCommand
()
->
resetSequence
(
$table
->
fullName
,
1
)
->
execute
();
}
}
/**
* @return TableSchema the schema information of the database table associated with this fixture.
* @throws \yii\base\InvalidConfigException if the table does not exist
*/
public
function
getTableSchema
()
{
if
(
$this
->
_table
!==
null
)
{
return
$this
->
_table
;
}
$db
=
$this
->
db
;
$tableName
=
$this
->
tableName
;
if
(
$tableName
===
null
)
{
/** @var \yii\db\ActiveRecord $modelClass */
$modelClass
=
$this
->
modelClass
;
$tableName
=
$modelClass
::
tableName
();
}
$this
->
_table
=
$db
->
getSchema
()
->
getTableSchema
(
$tableName
);
if
(
$this
->
_table
===
null
)
{
throw
new
InvalidConfigException
(
"Table does not exist:
{
$tableName
}
"
);
}
return
$this
->
_table
;
}
}
framework/test/BaseActiveFixture.php
View file @
b496a04f
...
...
@@ -27,16 +27,6 @@ abstract class BaseActiveFixture extends DbFixture implements \IteratorAggregate
*/
public
$modelClass
;
/**
* @var boolean whether to create the corresponding DB schema for this fixture.
* By setting this property to be true, the [[loadSchema()]] method will be called when the fixture is loaded.
*/
public
$loadSchema
=
true
;
/**
* @var boolean whether to load fixture data.
* By setting this property to be true, the [[loadData()]] method will be called when the fixture is loaded.
*/
public
$loadData
=
true
;
/**
* @var array the data rows. Each array element represents one row of data (column name => column value).
*/
public
$data
=
[];
...
...
@@ -47,21 +37,8 @@ abstract class BaseActiveFixture extends DbFixture implements \IteratorAggregate
/**
* @inheritdoc
*/
public
function
load
()
{
if
(
$this
->
loadSchema
)
{
$this
->
loadSchema
();
}
if
(
$this
->
loadData
)
{
$this
->
loadData
();
}
}
/**
* Returns the AR model by the specified model name.
* A model name is the key of the corresponding data row
returned by [[loadData()
]].
* A model name is the key of the corresponding data row
in [[data
]].
* @param string $name the model name.
* @return null|\yii\db\ActiveRecord the AR model, or null if the model cannot be found in the database
* @throws \yii\base\InvalidConfigException if [[modelClass]] is not set.
...
...
@@ -89,23 +66,4 @@ abstract class BaseActiveFixture extends DbFixture implements \IteratorAggregate
}
return
$this
->
_models
[
$name
]
=
$modelClass
::
find
(
$keys
);
}
/**
* Creates the database schema needed by this fixture.
* You may override this method by creating the DB table associated with this fixture
* and other relevant DB elements, such as views, triggers.
*/
protected
function
loadSchema
()
{
}
/**
* Loads the fixture data.
* The default implementation will first reset the DB table and then populate it with the data
* returned by [[getData()]].
*/
protected
function
loadData
()
{
return
[];
}
}
framework/test/DbFixture.php
View file @
b496a04f
...
...
@@ -14,7 +14,7 @@ use yii\db\Connection;
/**
* DbFixture is the base class for DB-related fixtures.
*
* DbFixture provides the [[db]] connection
as well as a set of commonly used DB manipulation method
s.
* DbFixture provides the [[db]] connection
to be used by DB fixture
s.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
...
...
@@ -41,256 +41,4 @@ abstract class DbFixture extends Fixture
throw
new
InvalidConfigException
(
"The 'db' property must be either a DB connection instance or the application component ID of a DB connection."
);
}
}
/**
* Executes a SQL statement.
* This method executes the specified SQL statement using [[db]].
* @param string $sql the SQL statement to be executed
* @param array $params input parameters (name => value) for the SQL execution.
* See [[Command::execute()]] for more details.
*/
public
function
execute
(
$sql
,
$params
=
[])
{
$this
->
db
->
createCommand
(
$sql
)
->
execute
(
$params
);
}
/**
* Creates and executes an INSERT SQL statement.
* The method will properly escape the column names, and bind the values to be inserted.
* @param string $table the table that new rows will be inserted into.
* @param array $columns the column data (name => value) to be inserted into the table.
*/
public
function
insert
(
$table
,
$columns
)
{
$this
->
db
->
createCommand
()
->
insert
(
$table
,
$columns
)
->
execute
();
}
/**
* Creates and executes an batch INSERT SQL statement.
* The method will properly escape the column names, and bind the values to be inserted.
* @param string $table the table that new rows will be inserted into.
* @param array $columns the column names.
* @param array $rows the rows to be batch inserted into the table
*/
public
function
batchInsert
(
$table
,
$columns
,
$rows
)
{
$this
->
db
->
createCommand
()
->
batchInsert
(
$table
,
$columns
,
$rows
)
->
execute
();
}
/**
* Creates and executes an UPDATE SQL statement.
* The method will properly escape the column names and bind the values to be updated.
* @param string $table the table to be updated.
* @param array $columns the column data (name => value) to be updated.
* @param array|string $condition the conditions that will be put in the WHERE part. Please
* refer to [[Query::where()]] on how to specify conditions.
* @param array $params the parameters to be bound to the query.
*/
public
function
update
(
$table
,
$columns
,
$condition
=
''
,
$params
=
[])
{
$this
->
db
->
createCommand
()
->
update
(
$table
,
$columns
,
$condition
,
$params
)
->
execute
();
}
/**
* Creates and executes a DELETE SQL statement.
* @param string $table the table where the data will be deleted from.
* @param array|string $condition the conditions that will be put in the WHERE part. Please
* refer to [[Query::where()]] on how to specify conditions.
* @param array $params the parameters to be bound to the query.
*/
public
function
delete
(
$table
,
$condition
=
''
,
$params
=
[])
{
$this
->
db
->
createCommand
()
->
delete
(
$table
,
$condition
,
$params
)
->
execute
();
}
/**
* Builds and executes a SQL statement for creating a new DB table.
*
* The columns in the new table should be specified as name-definition pairs (e.g. 'name' => 'string'),
* where name stands for a column name which will be properly quoted by the method, and definition
* stands for the column type which can contain an abstract DB type.
*
* The [[QueryBuilder::getColumnType()]] method will be invoked to convert any abstract type into a physical one.
*
* If a column is specified with definition only (e.g. 'PRIMARY KEY (name, type)'), it will be directly
* put into the generated SQL.
*
* @param string $table the name of the table to be created. The name will be properly quoted by the method.
* @param array $columns the columns (name => definition) in the new table.
* @param string $options additional SQL fragment that will be appended to the generated SQL.
*/
public
function
createTable
(
$table
,
$columns
,
$options
=
null
)
{
$this
->
db
->
createCommand
()
->
createTable
(
$table
,
$columns
,
$options
)
->
execute
();
}
/**
* Builds and executes a SQL statement for renaming a DB table.
* @param string $table the table to be renamed. The name will be properly quoted by the method.
* @param string $newName the new table name. The name will be properly quoted by the method.
*/
public
function
renameTable
(
$table
,
$newName
)
{
$this
->
db
->
createCommand
()
->
renameTable
(
$table
,
$newName
)
->
execute
();
}
/**
* Builds and executes a SQL statement for dropping a DB table.
* @param string $table the table to be dropped. The name will be properly quoted by the method.
*/
public
function
dropTable
(
$table
)
{
$this
->
db
->
createCommand
()
->
dropTable
(
$table
)
->
execute
();
}
/**
* Builds and executes a SQL statement for truncating a DB table.
* @param string $table the table to be truncated. The name will be properly quoted by the method.
*/
public
function
truncateTable
(
$table
)
{
$this
->
db
->
createCommand
()
->
truncateTable
(
$table
)
->
execute
();
}
/**
* Builds and executes a SQL statement for adding a new DB column.
* @param string $table the table that the new column will be added to. The table name will be properly quoted by the method.
* @param string $column the name of the new column. The name will be properly quoted by the method.
* @param string $type the column type. The [[QueryBuilder::getColumnType()]] method will be invoked to convert abstract column type (if any)
* into the physical one. Anything that is not recognized as abstract type will be kept in the generated SQL.
* For example, 'string' will be turned into 'varchar(255)', while 'string not null' will become 'varchar(255) not null'.
*/
public
function
addColumn
(
$table
,
$column
,
$type
)
{
$this
->
db
->
createCommand
()
->
addColumn
(
$table
,
$column
,
$type
)
->
execute
();
}
/**
* Builds and executes a SQL statement for dropping a DB column.
* @param string $table the table whose column is to be dropped. The name will be properly quoted by the method.
* @param string $column the name of the column to be dropped. The name will be properly quoted by the method.
*/
public
function
dropColumn
(
$table
,
$column
)
{
$this
->
db
->
createCommand
()
->
dropColumn
(
$table
,
$column
)
->
execute
();
}
/**
* Builds and executes a SQL statement for renaming a column.
* @param string $table the table whose column is to be renamed. The name will be properly quoted by the method.
* @param string $name the old name of the column. The name will be properly quoted by the method.
* @param string $newName the new name of the column. The name will be properly quoted by the method.
*/
public
function
renameColumn
(
$table
,
$name
,
$newName
)
{
$this
->
db
->
createCommand
()
->
renameColumn
(
$table
,
$name
,
$newName
)
->
execute
();
}
/**
* Builds and executes a SQL statement for changing the definition of a column.
* @param string $table the table whose column is to be changed. The table name will be properly quoted by the method.
* @param string $column the name of the column to be changed. The name will be properly quoted by the method.
* @param string $type the new column type. The [[getColumnType()]] method will be invoked to convert abstract column type (if any)
* into the physical one. Anything that is not recognized as abstract type will be kept in the generated SQL.
* For example, 'string' will be turned into 'varchar(255)', while 'string not null' will become 'varchar(255) not null'.
*/
public
function
alterColumn
(
$table
,
$column
,
$type
)
{
$this
->
db
->
createCommand
()
->
alterColumn
(
$table
,
$column
,
$type
)
->
execute
();
}
/**
* Builds and executes a SQL statement for creating a primary key.
* The method will properly quote the table and column names.
* @param string $name the name of the primary key constraint.
* @param string $table the table that the primary key constraint will be added to.
* @param string|array $columns comma separated string or array of columns that the primary key will consist of.
*/
public
function
addPrimaryKey
(
$name
,
$table
,
$columns
)
{
$this
->
db
->
createCommand
()
->
addPrimaryKey
(
$name
,
$table
,
$columns
)
->
execute
();
}
/**
* Builds and executes a SQL statement for dropping a primary key.
* @param string $name the name of the primary key constraint to be removed.
* @param string $table the table that the primary key constraint will be removed from.
*/
public
function
dropPrimaryKey
(
$name
,
$table
)
{
$this
->
db
->
createCommand
()
->
dropPrimaryKey
(
$name
,
$table
)
->
execute
();
}
/**
* Builds a SQL statement for adding a foreign key constraint to an existing table.
* The method will properly quote the table and column names.
* @param string $name the name of the foreign key constraint.
* @param string $table the table that the foreign key constraint will be added to.
* @param string $columns the name of the column to that the constraint will be added on. If there are multiple columns, separate them with commas.
* @param string $refTable the table that the foreign key references to.
* @param string $refColumns the name of the column that the foreign key references to. If there are multiple columns, separate them with commas.
* @param string $delete the ON DELETE option. Most DBMS support these options: RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL
* @param string $update the ON UPDATE option. Most DBMS support these options: RESTRICT, CASCADE, NO ACTION, SET DEFAULT, SET NULL
*/
public
function
addForeignKey
(
$name
,
$table
,
$columns
,
$refTable
,
$refColumns
,
$delete
=
null
,
$update
=
null
)
{
$this
->
db
->
createCommand
()
->
addForeignKey
(
$name
,
$table
,
$columns
,
$refTable
,
$refColumns
,
$delete
,
$update
)
->
execute
();
}
/**
* Builds a SQL statement for dropping a foreign key constraint.
* @param string $name the name of the foreign key constraint to be dropped. The name will be properly quoted by the method.
* @param string $table the table whose foreign is to be dropped. The name will be properly quoted by the method.
*/
public
function
dropForeignKey
(
$name
,
$table
)
{
$this
->
db
->
createCommand
()
->
dropForeignKey
(
$name
,
$table
)
->
execute
();
}
/**
* Builds and executes a SQL statement for creating a new index.
* @param string $name the name of the index. The name will be properly quoted by the method.
* @param string $table the table that the new index will be created for. The table name will be properly quoted by the method.
* @param string $column the column(s) that should be included in the index. If there are multiple columns, please separate them
* by commas. The column names will be properly quoted by the method.
* @param boolean $unique whether to add UNIQUE constraint on the created index.
*/
public
function
createIndex
(
$name
,
$table
,
$column
,
$unique
=
false
)
{
$this
->
db
->
createCommand
()
->
createIndex
(
$name
,
$table
,
$column
,
$unique
)
->
execute
();
}
/**
* Builds and executes a SQL statement for dropping an index.
* @param string $name the name of the index to be dropped. The name will be properly quoted by the method.
* @param string $table the table whose index is to be dropped. The name will be properly quoted by the method.
*/
public
function
dropIndex
(
$name
,
$table
)
{
$this
->
db
->
createCommand
()
->
dropIndex
(
$name
,
$table
)
->
execute
();
}
/**
* Creates and executes a SQL command to reset the sequence value of a table's primary key.
* The sequence will be reset such that the primary key of the next new row inserted
* will have the specified value or 1.
* @param string $table the name of the table whose primary key sequence will be reset
* @param mixed $value the value for the primary key of the next new row inserted. If this is not set,
* the next new row's primary key will have a value 1.
*/
public
function
resetSequence
(
$table
,
$value
=
null
)
{
$this
->
db
->
createCommand
()
->
resetSequence
(
$table
,
$value
)
->
execute
();
}
/**
* Builds and executes a SQL command for enabling or disabling integrity check.
* @param boolean $check whether to turn on or off the integrity check.
* @param string $schema the schema name of the tables. Defaults to empty string, meaning the current
* or default schema.
* @param string $table the table name.
*/
public
function
checkIntegrity
(
$check
=
true
,
$schema
=
''
,
$table
=
''
)
{
$this
->
db
->
createCommand
()
->
checkIntegrity
(
$check
,
$schema
,
$table
)
->
execute
();
}
}
framework/test/DbFixtureManager.php
deleted
100644 → 0
View file @
12eca516
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace
yii\test
;
use
Yii
;
use
yii\base\Component
;
use
yii\base\InvalidConfigException
;
use
yii\db\ActiveRecord
;
use
yii\db\Connection
;
/**
* DbFixtureManager manages database fixtures during tests.
*
* A fixture represents a list of rows for a specific table. For a test method,
* using a fixture means that at the beginning of the method, the table has and only
* has the rows that are given in the fixture. Therefore, the table's state is
* predictable.
*
* A fixture is represented as a PHP script whose name (without suffix) is the
* same as the table name (if schema name is needed, it should be prefixed to
* the table name). The PHP script returns an array representing a list of table
* rows. Each row is an associative array of column values indexed by column names.
*
* Fixtures must be stored under the [[basePath]] directory. The directory
* may contain a file named `init.php` which will be executed before any fixture is loaded.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class
DbFixtureManager
extends
Component
{
/**
* @var string the init script file that should be executed before running each test.
* This should be a path relative to [[basePath]].
*/
public
$initScript
=
'init.php'
;
/**
* @var string the base path containing all fixtures. This can be either a directory path or path alias.
*/
public
$basePath
=
'@app/tests/fixtures'
;
/**
* @var Connection|string the DB connection object or the application component ID of the DB connection.
* After the DbFixtureManager object is created, if you want to change this property, you should only assign it
* with a DB connection object.
*/
public
$db
=
'db'
;
/**
* @var array list of database schemas that the test tables may reside in. Defaults to
* [''], meaning using the default schema (an empty string refers to the
* default schema). This property is mainly used when turning on and off integrity checks
* so that fixture data can be populated into the database without causing problem.
*/
public
$schemas
=
[
''
];
private
$_rows
;
// fixture name, row alias => row
private
$_models
;
// fixture name, row alias => record (or class name)
/**
* Loads the specified fixtures.
*
* This method does the following things to load the fixtures:
*
* - Run [[initScript]] if any.
* - Clean up data and models loaded in memory previously.
* - Load each specified fixture by calling [[loadFixture()]].
*
* @param array $fixtures a list of fixtures (fixture name => table name or AR class name) to be loaded.
* Each array element can be either a table name (with schema prefix if needed), or a fully-qualified
* ActiveRecord class name (e.g. `app\models\Post`). An element can be associated with a key
* which will be treated as the fixture name.
* @return array the loaded fixture data (fixture name => table rows)
* @throws InvalidConfigException if a model class specifying a fixture is not an ActiveRecord class.
*/
public
function
load
(
array
$fixtures
=
[])
{
$this
->
basePath
=
Yii
::
getAlias
(
$this
->
basePath
);
if
(
is_string
(
$this
->
db
))
{
$this
->
db
=
Yii
::
$app
->
getComponent
(
$this
->
db
);
}
if
(
!
$this
->
db
instanceof
Connection
)
{
throw
new
InvalidConfigException
(
"The 'db' property must be either a DB connection instance or the application component ID of a DB connection."
);
}
foreach
(
$fixtures
as
$name
=>
$fixture
)
{
if
(
strpos
(
$fixture
,
'\\'
)
!==
false
)
{
$model
=
new
$fixture
;
if
(
$model
instanceof
ActiveRecord
)
{
$fixtures
[
$name
]
=
$model
->
getTableSchema
()
->
name
;
}
else
{
throw
new
InvalidConfigException
(
"Fixture '
$fixture
' must be an ActiveRecord class."
);
}
}
}
$this
->
_rows
=
$this
->
_models
=
[];
$this
->
checkIntegrity
(
false
);
if
(
!
empty
(
$this
->
initScript
))
{
$initFile
=
$this
->
basePath
.
'/'
.
$this
->
initScript
;
if
(
is_file
(
$initFile
))
{
require
(
$initFile
);
}
}
foreach
(
$fixtures
as
$name
=>
$tableName
)
{
$rows
=
$this
->
loadFixture
(
$tableName
);
if
(
is_array
(
$rows
))
{
$this
->
_rows
[
$name
]
=
$rows
;
}
}
$this
->
checkIntegrity
(
true
);
return
$this
->
_rows
;
}
/**
* Loads the fixture for the specified table.
*
* This method does the following tasks to load the fixture for a table:
*
* - Remove existing rows in the table.
* - If there is any auto-incremental column, the corresponding sequence will be reset to 0.
* - If a fixture file is found, it will be executed, and its return value will be treated
* as rows which will then be inserted into the table.
*
* @param string $tableName table name
* @return array|boolean the loaded fixture rows indexed by row aliases (if any).
* False is returned if the table does not have a fixture.
* @throws InvalidConfigException if the specified table does not exist
*/
public
function
loadFixture
(
$tableName
)
{
$table
=
$this
->
db
->
getSchema
()
->
getTableSchema
(
$tableName
);
if
(
$table
===
null
)
{
throw
new
InvalidConfigException
(
"Table does not exist:
$tableName
"
);
}
$this
->
db
->
createCommand
()
->
delete
(
$tableName
)
->
execute
();
$this
->
db
->
createCommand
()
->
resetSequence
(
$tableName
,
1
)
->
execute
();
$fileName
=
$this
->
basePath
.
'/'
.
$tableName
.
'.php'
;
if
(
!
is_file
(
$fileName
))
{
return
false
;
}
$rows
=
[];
foreach
(
require
(
$fileName
)
as
$alias
=>
$row
)
{
$this
->
db
->
createCommand
()
->
insert
(
$tableName
,
$row
)
->
execute
();
if
(
$table
->
sequenceName
!==
null
)
{
foreach
(
$table
->
primaryKey
as
$pk
)
{
if
(
!
isset
(
$row
[
$pk
]))
{
$row
[
$pk
]
=
$this
->
db
->
getLastInsertID
(
$table
->
sequenceName
);
break
;
}
}
}
$rows
[
$alias
]
=
$row
;
}
return
$rows
;
}
/**
* Returns the fixture data rows.
* The rows will have updated primary key values if the primary key is auto-incremental.
* @param string $fixtureName the fixture name
* @return array the fixture data rows. False is returned if there is no such fixture data.
*/
public
function
getRows
(
$fixtureName
)
{
return
isset
(
$this
->
_rows
[
$fixtureName
])
?
$this
->
_rows
[
$fixtureName
]
:
false
;
}
/**
* Returns the specified ActiveRecord instance in the fixture data.
* @param string $fixtureName the fixture name
* @param string $modelName the alias for the fixture data row
* @return ActiveRecord the ActiveRecord instance. Null is returned if there is no such fixture row.
*/
public
function
getModel
(
$fixtureName
,
$modelName
)
{
if
(
!
isset
(
$this
->
_rows
[
$fixtureName
][
$modelName
]))
{
return
null
;
}
if
(
isset
(
$this
->
_models
[
$fixtureName
][
$modelName
]))
{
return
$this
->
_models
[
$fixtureName
][
$modelName
];
}
$row
=
$this
->
_rows
[
$fixtureName
][
$modelName
];
/** @var ActiveRecord $modelClass */
$modelClass
=
$this
->
_models
[
$fixtureName
];
/** @var ActiveRecord $model */
$model
=
new
$modelClass
;
$keys
=
[];
foreach
(
$model
->
primaryKey
()
as
$key
)
{
$keys
[
$key
]
=
isset
(
$row
[
$key
])
?
$row
[
$key
]
:
null
;
}
return
$this
->
_models
[
$fixtureName
][
$modelName
]
=
$modelClass
::
find
(
$keys
);
}
/**
* Enables or disables database integrity check.
* This method may be used to temporarily turn off foreign constraints check.
* @param boolean $check whether to enable database integrity check
*/
public
function
checkIntegrity
(
$check
)
{
foreach
(
$this
->
schemas
as
$schema
)
{
$this
->
db
->
createCommand
()
->
checkIntegrity
(
$check
,
$schema
)
->
execute
();
}
}
}
framework/test/DbTestTrait.php
deleted
100644 → 0
View file @
12eca516
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace
yii\test
;
use
Yii
;
/**
* DbTestTrait implements the commonly used methods for setting up and accessing fixture data.
*
* To use DbTestTrait, call the [[loadFixtures()]] method in the setup method in a test case class.
* The specified fixtures will be loaded and accessible through [[getFixtureData()]] and [[getFixtureModel()]].
*
* For example,
*
* ~~~
* use yii\test\DbTestTrait;
* use yii\codeception\TestCase;
* use app\models\Post;
* use app\models\User;
*
* class PostTestCase extends TestCase
* {
* use DbTestTrait;
*
* protected function setUp()
* {
* parent::setUp();
*
* $this->loadFixtures([
* 'posts' => Post::className(),
* 'users' => User::className(),
* ]);
* }
* }
* ~~~
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
trait
DbTestTrait
{
/**
* Loads the specified fixtures.
*
* This method should typically be called in the setup method of test cases so that
* the fixtures are loaded before running each test method.
*
* This method does the following things:
*
* - Run [[DbFixtureManager::initScript]] if it is found under [[DbFixtureManager::basePath]].
* - Clean up data and models loaded in memory previously.
* - Load each specified fixture:
* * Truncate the corresponding table.
* * If a fixture file named `TableName.php` is found under [[DbFixtureManager::basePath]],
* the file will be executed, and the return value will be treated as rows which will
* then be inserted into the table.
*
* @param array $fixtures a list of fixtures (fixture name => table name or AR class name) to be loaded.
* Each array element can be either a table name (with schema prefix if needed), or a fully-qualified
* ActiveRecord class name (e.g. `app\models\Post`). An element can be optionally associated with a key
* which will be treated as the fixture name. For example,
*
* ~~~
* [
* 'tbl_comment',
* 'users' => 'tbl_user', // 'users' is the fixture name, 'tbl_user' is a table name
* 'posts' => 'app\models\Post, // 'app\models\Post' is a model class name
* ]
* ~~~
*
* @return array the loaded fixture data (fixture name => table rows)
*/
public
function
loadFixtures
(
array
$fixtures
=
[])
{
return
$this
->
getFixtureManager
()
->
load
(
$fixtures
);
}
/**
* Returns the DB fixture manager.
* @return DbFixtureManager the DB fixture manager
*/
public
function
getFixtureManager
()
{
return
Yii
::
$app
->
getComponent
(
'fixture'
);
}
/**
* Returns the table rows of the named fixture.
* @param string $fixtureName the fixture name.
* @return array the named fixture table rows. False is returned if there is no such fixture data.
*/
public
function
getFixtureRows
(
$fixtureName
)
{
return
$this
->
getFixtureManager
()
->
getRows
(
$fixtureName
);
}
/**
* Returns the named AR instance corresponding to the named fixture.
* @param string $fixtureName the fixture name.
* @param string $modelName the name of the fixture data row
* @return \yii\db\ActiveRecord the named AR instance corresponding to the named fixture.
* Null is returned if there is no such fixture or the record cannot be found.
*/
public
function
getFixtureModel
(
$fixtureName
,
$modelName
)
{
return
$this
->
getFixtureManager
()
->
getModel
(
$fixtureName
,
$modelName
);
}
}
framework/test/InitDbFixture.php
View file @
b496a04f
...
...
@@ -71,4 +71,15 @@ class InitDbFixture extends DbFixture
require
(
$file
);
}
}
/**
* Toggles the DB integrity check.
* @param boolean $check whether to turn on or off the integrity check.
*/
public
function
checkIntegrity
(
$check
)
{
foreach
(
$this
->
schemas
as
$schema
)
{
$this
->
db
->
createCommand
()
->
checkIntegrity
(
$check
,
$schema
)
->
execute
();
}
}
}
tests/unit/framework/test/ActiveFixtureTest.php
View file @
b496a04f
...
...
@@ -8,37 +8,15 @@
namespace
yiiunit\framework\test
;
use
yii\test\ActiveFixture
;
use
yiiunit\data\ar\ActiveRecord
;
use
yii\test\FixtureTrait
;
use
yii\test\InitDbFixture
;
use
yiiunit\data\ar\
ActiveRecord
;
use
yiiunit\data\ar\
Customer
;
use
yiiunit\framework\db\DatabaseTestCase
;
class
Customer
extends
ActiveRecord
{
public
static
function
tableName
()
{
return
'tbl_customer2'
;
}
}
class
CustomerFixture
extends
ActiveFixture
{
public
$modelClass
=
'yiiunit\framework\test\Customer'
;
protected
function
loadSchema
()
{
try
{
$this
->
dropTable
(
'tbl_customer2'
);
}
catch
(
\Exception
$e
)
{
}
$this
->
createTable
(
'tbl_customer2'
,
[
'id'
=>
'pk'
,
'email'
=>
'string'
,
'name'
=>
'string'
,
'address'
=>
'string'
,
'status'
=>
'integer'
,
]);
}
public
$modelClass
=
'yiiunit\data\ar\Customer'
;
}
class
MyDbTestCase
...
...
@@ -81,7 +59,7 @@ class ActiveFixtureTest extends DatabaseTestCase
{
parent
::
setUp
();
\Yii
::
$app
->
setComponent
(
'db'
,
$this
->
getConnection
());
Customer
::
$db
=
$this
->
getConnection
();
ActiveRecord
::
$db
=
$this
->
getConnection
();
}
public
function
tearDown
()
...
...
tests/unit/framework/test/data/tbl_customer
2
.php
→
tests/unit/framework/test/data/tbl_customer.php
View file @
b496a04f
File moved
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