定義 Fixtures
=================

自動測試需要被執行很多次。為了確保測試過程是可以重複的，我們很想要在一些可知的狀態下進行測試，這個狀態我們稱之為 *Fixtures*。舉個例子，在一個部落格應用程式中測試文章建立功能，每次當我們進行測試時, 與文章相關的資料表（例如：`Post` 資料表、`Comment` 資料表）應該被恢復到一個特定的狀態下。[PHPUnit 檔案](http://www.phpunit.de/manual/current/en/fixtures.html) 已詳細地描述了一個廣泛 Fixture 設定。 而本節主要介紹怎樣像剛才描述的例子那樣構建資料庫 Fixture。

設置構建資料庫的 Fixture，恐怕是以資料庫為後端支援的應用程式最耗時的部分之一。Yii 引進的 [CBbFixtureManager] 應用程式元件可以有效的減輕這一問題。當進行一組測試的時候，它基本上會做以下這些事情：

 * 在所有測試運行之前，它重置測試相關資料為可知的狀態。
 * 在單個測試運行之前，它將特定的表重置為可知狀態。
 * 在一個測試方法執行過程中，它提供了供給 Fixture 的列資料的存取接口.

請按照下述方法使用我們在 [應用程式配置](/doc/guide/basics.application#application-configuration) 中配置的 [CDbFixtureManager].

~~~
[php]
return array(
	'components'=>array(
		'fixture'=>array(
			'class'=>'system.test.CDbFixtureManager',
		),
	),
);
~~~

然後我們在目錄 `protected/tests/fixtures` 下提供一個 Fixture 資料，這個目錄可以通過配置應用程式配置檔案中的 [CDbFixtureManager::basePath] 屬性指定為其他目錄。Fixture 資料是由多個稱之為 Fixture 檔案的 PHP 檔案組合而成。每個 Fixture 檔案返回一個陣列，代表資料的一個特定資料表的初始列。檔案名和資料表名相同。以下則是將 `Post` 表的 Fixture 資料儲存於名為 `Post.php` 檔案裡的例子。

~~~
[php]
<?php
return array(
	'sample1'=>array(
		'title'=>'test post 1',
		'content'=>'test post content 1',
		'createTime'=>1230952187,
		'authorId'=>1,
	),
	'sample2'=>array(
		'title'=>'test post 2',
		'content'=>'test post content 2',
		'createTime'=>1230952287,
		'authorId'=>1,
	),
);
~~~

正如我們所見，上面返回了兩列資料，每一列都表示一個陣列，其鍵是表的字串名，其值則是對應的字串值。每列的索引都是稱之為*列別名*的字串（例如：`simple1`、`simple2`）。稍後當我們撰寫測試腳本的時候，我們可以方便地通過它的別名調用這列資料。我們將在下節中詳細的介紹這個。

你也許注意到了我們並未在上述 Fixture 中指定 `id` 字串的值。這是因為 `id` 字串已經被定義為自動遞增主鍵了，它的值也會在我們插入新資料的時候自動產生。

當 [CDbFixtureManager] 第一次被引用時，它會仔細檢查所有的 Fixture 檔案然後使用他們重置對應的資料表。它通過清空資料表，重置資料表主鍵的自動遞增序列值，然後插入來自 Fixture 檔案的資料列到資料表中來重置資料表.

有時候，我們可能不想在一套測試前重置 Fixture 檔案裡描述的每一個表，因為重置太多的 Fixture 檔案可能需要很多時間。這種情況下，我們可以寫一個 PHP 腳本來定制這個初始化過程。這個腳本應該被儲存在存放 Fixture 檔案的目錄下，並命名為 `init.php`。當 [CDbFixtureManager] 檢測到了這個腳本的存在，它將執行這個腳本而不是重置每一個資料表。

不喜歡使用預設方式來重置資料表也是可以的，例如：清空資料表然後插入 Fixture 資料，如果是這種情況，我們可以為指定的 Fixture 檔案撰寫一個初始化腳本。這個腳本必須名稱為資料表名+`.init.php`。例如：`Post` 資料表的初始化腳本檔案就是 `Post.init.php`。當 [CDbFixtureManager] 發現了這個腳本，它將執行這個腳本而不是採用預設的方式去重置該資料表。

> Tip: 太多的 Fixture 檔案大大延長了測試時間。因此，你應該只為那些在測試中資料會發生變化的表提供 Fixture 檔案。那些做為查找服務的資料表不會改變，因此不需要 Fixture 檔案。

接下來兩節，我們將談到如何在單元測試和功能測試中使用被 [CDbFixtureManager] 管理的 Fixture。

<div class="revision">$Id$</div>
