Reputation: 6858
I am writing a PHPUnit test for my Yii application. I read here:
Tip: Having too many fixture files could increase the test time dramatically. For this reason, you should only provide fixture files for those tables whose content may change during the test. Tables that serve as look-ups do not change and thus do not need fixture files.
I indeed have a large fixture (180 records, which takes >20 seconds to load), which is only used as a look-up. However, I do need to transform it easily from an associative array into a Model object, like you can usually do with the fixture syntax below. The tip suggests that there is also a way to create a Model object without the use of a fixture, but does not mention how this is done. Can anyone help out?
Creation of Model object with a fixture:
// tests/fixtures/Order.php
return array(
'row_id' => array(
'id' => 1,
'name' => 'hello',
)
)
// tests/unit/AbcTest.php
public $fixtures = array(
'orders' => 'Order',
)
public test_abc()
{
$order = $this->orders('row_id');
....
}
Upvotes: 5
Views: 772
Reputation: 17091
Another option:
when you create db migration you should apply it on production db and on test db moreover you should populate test tables with test data.
Benefits of this approach:
For example:
<?php
class m150608_110143_init extends CDbMigration
{
public function safeUp()
{
$sql1 = "
CREATE TABLE brand (
id INT AUTO_INCREMENT,
name VARCHAR(100) NOT NULL DEFAULT '',
country VARCHAR(50) NOT NULL DEFAULT '',
PRIMARY KEY (id)
);
";
$sql2 = "
INSERT INTO brand VALUES
(null, 'aston martin', 'UK'),
(null, 'audi', 'Germany'),
(null, 'bmw', 'Germany'),
(null, 'citroen', 'France'),
(null, 'peugeot', 'France'),
(null, 'porsche', 'Germany'),
(null, 'toyota', 'Japan'),
(null, 'ferrari', 'Italy')
;
";
// Production db.
$this->setDbConnection(Yii::app()->db);
$this->execute($sql1);
// Test db.
$this->setDbConnection(Yii::app()->dbUnitTest);
$this->execute($sql1);
// Populate test db with fixtures.
$this->execute($sql2);
return true;
}
public function down()
{
$sql = 'DROP TABLE brand;';
// Test db.
$this->setDbConnection(Yii::app()->dbUnitTest);
$this->execute($sql);
// Production db.
$this->setDbConnection(Yii::app()->db);
$this->execute($sql);
return true;
}
}
And in test you don't have to think about fixtures.
Upvotes: 3
Reputation: 17091
Yes, it's possible to reach what you wish.
For example: i have model brand that have own fixture:
<?php
// protected/tests/fixtures/brand.php
return [
1 => [
'name' => 'Lexus',
'country' => 'JPN',
],
2 => [
'name' => 'Acura',
'country' => 'JPNE',
],
];
and i have next code:
$brand = new Brand;
$allBrands = $brand->findAll();
This code will return array with 2 CActiveRecord objects. And everything what we need - it's just build the same array with 2 CActiveRecord objects:
public function testGetAllAvailableBrands()
{
// Get brands from fixture.
$brand = new Brand;
$allBrandsFromFixture = $brand->findAll();
// Generate brands.
$lexus = new Brand;
$lexus->scenario = 'update';
$lexus->name = 'Lexus';
$lexus->country = 'JPN';
$lexus->id = 1;
$lexus->setPrimaryKey(1);
$lexus->setIsNewRecord(false);
$allBrandsGeneratedAtRuntime[] = $lexus;
$acura = new Brand;
$acura->scenario = 'update';
$acura->name = 'Acura';
$acura->country = 'JPNE';
$acura->id = 2;
$acura->setPrimaryKey(2);
$acura->setIsNewRecord(false);
$allBrandsGeneratedAtRuntime[] = $acura;
// Brands from fixture should be equals to generated brands.
$this->assertEquals($allBrandsFromFixture, $allBrandsGeneratedAtRuntime);
}
This test will be green because our brands exactly the same. You cat try something like this.
But i think that native yii fixtures looks much better, and to avoid increase the test time you should use .init.php files...
Upvotes: 1