定義 Fixtures
自動測試需要被執行很多次。為了確保測試過程是可以重複的,我們很想要在一些可知的狀態下進行測試,這個狀態我們稱之為 Fixtures。舉個例子,在一個部落格應用程式中測試文章建立功能,每次當我們進行測試時, 與文章相關的資料表(例如:Post
資料表、Comment
資料表)應該被恢復到一個特定的狀態下。PHPUnit 檔案 已詳細地描述了一個廣泛 Fixture 設定。 而本節主要介紹怎樣像剛才描述的例子那樣構建資料庫 Fixture。
設置構建資料庫的 Fixture,恐怕是以資料庫為後端支援的應用程式最耗時的部分之一。Yii 引進的 CBbFixtureManager 應用程式元件可以有效的減輕這一問題。當進行一組測試的時候,它基本上會做以下這些事情:
- 在所有測試運行之前,它重置測試相關資料為可知的狀態。
- 在單個測試運行之前,它將特定的表重置為可知狀態。
- 在一個測試方法執行過程中,它提供了供給 Fixture 的列資料的存取接口.
請按照下述方法使用我們在 應用程式配置 中配置的 CDbFixtureManager.
return array( 'components'=>array( 'fixture'=>array( 'class'=>'system.test.CDbFixtureManager', ), ), );
然後我們在目錄 protected/tests/fixtures
下提供一個 Fixture 資料,這個目錄可以通過配置應用程式配置檔案中的 CDbFixtureManager::basePath 屬性指定為其他目錄。Fixture 資料是由多個稱之為 Fixture 檔案的 PHP 檔案組合而成。每個 Fixture 檔案返回一個陣列,代表資料的一個特定資料表的初始列。檔案名和資料表名相同。以下則是將 Post
表的 Fixture 資料儲存於名為 Post.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。