fixture作成の省力化

またまたしばらく更新していなかったけど、メモ代わり。

CakePHPのbakeは素晴らしい機能で、色んな雛形を焼いてくれます。fixtureも焼いてくれるんだけど、今回はその話です。

まず、よくあるfixtureの焼き方で、例えば以下のようなbake。

[sysadmin@localhost Console]$ ./cake bake fixture -app /home/sysadmin/workspace/test/sample/app

Welcome to CakePHP v2.2.1 Console
---------------------------------------------------------------
App : app
Path: /home/sysadmin/workspace/test/sample/app/
---------------------------------------------------------------
---------------------------------------------------------------
Bake Fixture
Path: /home/sysadmin/workspace/test/sample/app/Test/Fixture/
---------------------------------------------------------------
Possible Models based on your current database:
 1. Hoge
 ・
 ・
 7. Address
 ・
 ・
17. Fuga
Enter a number from the list above,
type in the name of another model, or 'q' to exit  
[q] > 7
Would you like to import schema for this fixture? (y/n) 
[n] > y
Would you like to use record importing for this fixture? (y/n) 
[n] > y

Baking test fixture for Address...

File `/home/sysadmin/workspace/test/sample/app/Test/Fixture/AddressFixture.php` exists
Do you want to overwrite? (y/n/q) 
[n] > y
Wrote `/home/sysadmin/workspace/test/sample/app/Test/Fixture/AddressFixture.php`

で、焼かれるfixtureの内容は以下のようになります。

<?php
/**
 * AddressFixture
 *
 */
class AddressFixture extends CakeTestFixture {

/**
 * Import
 *
 * @var array
 */
	public $import = array('model' => 'Address', 'records' => true);

}

上記のfixtureの場合は、テストの都度、defaultのDBからtestのDBにschemaやrecordをインポートして、その内容でテストを行われることになります。これはこれでいいのですが、万一、defaultのDBの内容を書き換えてしまった場合、せっかく書いたテストも書き換える羽目になりかねません。

なお、上記ダイアログでy/nを変えることで、テストの都度のインポートではなく、サンプル的なrecordの内容をべた書きに焼いてくれたりしますが、あくまでCakePHPが吐き出すサンプルレコードですので、内容は何やら分かり辛いし、別のテーブルと何らかの依存関係があったとしても、その依存関係は必ずしも妥当になるとは言えません。これを編集して妥当なfixtureを作成するのもいいのですが、単純なテーブル構造ならいざ知らず、HABTMやら何やらがでてきたりすると、依存関係が面倒でもう一気にやってられなくなります。

というわけで以下のようにします。-rをつけるのがミソです。

[sysadmin@localhost Console]$ ./cake bake fixture -app /home/sysadmin/workspace/test/sample/app -r

Welcome to CakePHP v2.2.1 Console
---------------------------------------------------------------
App : app
Path: /home/sysadmin/workspace/test/sample/app/
---------------------------------------------------------------
---------------------------------------------------------------
Bake Fixture
Path: /home/sysadmin/workspace/test/sample/app/Test/Fixture/
---------------------------------------------------------------
Possible Models based on your current database:
 1. Hoge
 ・
 ・
 7. Address
 ・
 ・
17. Fuga
Enter a number from the list above,
type in the name of another model, or 'q' to exit  
[q] > 7
Would you like to import schema for this fixture? (y/n) 
[n] > y
Would you like to use record importing for this fixture? (y/n) 
[n] > 
Would you like to build this fixture with data from Address's table? (y/n) 
[n] > y
Please provide a SQL fragment to use as conditions
Example: WHERE 1=1  
[WHERE 1=1] > 
How many records do you want to import?  
[10] > 

Baking test fixture for Address...

File `/home/sysadmin/workspace/test/sample/app/Test/Fixture/AddressFixture.php` exists
Do you want to overwrite? (y/n/q) 
[n] > y
Wrote `/home/sysadmin/workspace/test/sample/app/Test/Fixture/AddressFixture.php`

で、生成されるfixtureは、以下のような感じ。

<?php
/**
 * AddressFixture
 *
 */
class AddressFixture extends CakeTestFixture {

/**
 * Import
 *
 * @var array
 */
	public $import = array('model' => 'Address');

/**
 * Records
 *
 * @var array
 */
	public $records = array(
		array(
			'id' => '1',
             ・
             ・
			'created' => '2012-07-23 17:18:24',
			'modified' => '2012-07-23 17:18:24'
		),
		array(
			'id' => '2',
             ・
             ・
			'created' => '2012-07-23 17:41:16',
			'modified' => '2012-07-23 17:41:16'
		),
		array(
			'id' => '3',
             ・
             ・
			'created' => '2012-07-24 10:02:55',
			'modified' => '2012-07-24 10:04:07'
		),
	);

}

実際のテーブルの内容を反映したfixtureを焼いてくれるので、テーブル間の依存関係も保持した妥当なrecordを生成してくれます。

ちなみに、
Please provide a SQL fragment to use as conditions
やら
How many records do you want to import?
あたりを指定すれば、お好みのrecordを抽出したfixtureを作成できます。

上記のようにfixtureを焼いて、それを必要に応じて内容を編集することで、fixtureの作成の省力化をはかることができます。

以上。

※追記
いちいち対話式でmodel一つ一つbakeするのも面倒ですので、実際は以下のように一気にbakeすることが多いんじゃないかと思います。
なお、問答無用で上書きでfixtureが生成されますので注意のこと。

./cake bake fixture -app /home/sysadmin/workspace/test/sample/app -r -n 100 all