夾具是測試的重要組成部分。它們的主要目的是在一個固定/已知的狀態下設定環境,以便您的測試是可重複的,並以預期的方式執行。Yii 提供了一個夾具框架,讓您可以精確地定義夾具,並在 Codeception 中執行測試以及獨立執行測試時輕鬆地使用它們。
Yii 夾具框架中的一個關鍵概念是所謂的夾具物件。夾具物件代表測試環境的特定方面,並且是 yii\test\Fixture 或其子類別的實例。例如,您可以使用 UserFixture
來確保使用者資料庫表包含一組固定的資料。您可以在執行測試之前載入一個或多個夾具物件,並在完成時卸載它們。
夾具可以依賴其他夾具,透過其 yii\test\Fixture::$depends 屬性指定。當夾具正在載入時,它所依賴的夾具將在該夾具之前自動載入;並且當夾具正在卸載時,依賴的夾具將在該夾具之後卸載。
要定義夾具,請建立一個新的類別,擴充 yii\test\Fixture 或 yii\test\ActiveFixture。前者最適合用於通用夾具,而後者具有專門為與資料庫和 ActiveRecord 協同運作而設計的增強功能。
以下程式碼定義了關於 User
ActiveRecord 和相應使用者表的夾具。
<?php
namespace app\tests\fixtures;
use yii\test\ActiveFixture;
class UserFixture extends ActiveFixture
{
public $modelClass = 'app\models\User';
}
提示:每個
ActiveFixture
都是關於為測試目的準備資料庫表。您可以透過設定 yii\test\ActiveFixture::$tableName 屬性或 yii\test\ActiveFixture::$modelClass 屬性來指定表。如果是後者,表名稱將從modelClass
指定的ActiveRecord
類別中取得。
注意:yii\test\ActiveFixture 僅適用於 SQL 資料庫。對於 NoSQL 資料庫,Yii 提供了以下
ActiveFixture
類別
- Mongo DB:yii\mongodb\ActiveFixture
- Elasticsearch:yii\elasticsearch\ActiveFixture(自 2.0.2 版本起)
ActiveFixture
夾具的夾具資料通常在位於 fixturepath/data/tablename.php
的檔案中提供,其中 fixturepath
代表包含夾具類別檔案的目錄,而 tablename
是與夾具關聯的表的名稱。在上面的範例中,該檔案應為 @app/tests/fixtures/data/user.php
。資料檔案應傳回要插入使用者表中的資料列陣列。例如,
<?php
return [
'user1' => [
'username' => 'lmayert',
'email' => 'strosin.vernice@jerde.com',
'auth_key' => 'K3nF70it7tzNsHddEiq0BZ0i-OU8S3xV',
'password' => '$2y$13$WSyE5hHsG1rWN2jV8LRHzubilrCLI5Ev/iK0r3jRuwQEs2ldRu.a2',
],
'user2' => [
'username' => 'napoleon69',
'email' => 'aileen.barton@heaneyschumm.com',
'auth_key' => 'dZlXsVnIDgIzFgX4EduAqkEPuphhOh9q',
'password' => '$2y$13$kkgpvJ8lnjKo8RuoR30ay.RjDf15bMcHIF7Vz1zz/6viYG5xJExU6',
],
];
您可以為列賦予別名,以便稍後在您的測試中,您可以透過別名引用該列。在上面的範例中,兩列分別被別名為 user1
和 user2
。
此外,您不需要為自動遞增的列指定資料。當夾具正在載入時,Yii 將自動將實際值填入列中。
提示:您可以透過設定 yii\test\ActiveFixture::$dataFile 屬性來自訂資料檔案的位置。您也可以覆寫 yii\test\ActiveFixture::getData() 以提供資料。
正如我們之前描述的,夾具可以依賴其他夾具。例如,UserProfileFixture
可能需要依賴 UserFixture
,因為使用者個人資料表包含指向使用者表的外鍵。依賴關係透過 yii\test\Fixture::$depends 屬性指定,如下所示,
namespace app\tests\fixtures;
use yii\test\ActiveFixture;
class UserProfileFixture extends ActiveFixture
{
public $modelClass = 'app\models\UserProfile';
public $depends = ['app\tests\fixtures\UserFixture'];
}
依賴關係也確保了夾具以明確定義的順序載入和卸載。在上面的範例中,UserFixture
將始終在 UserProfileFixture
之前載入,以確保所有外鍵參考都存在,並且在 UserProfileFixture
卸載後卸載,原因相同。
在上面,我們展示了如何定義關於資料庫表的夾具。要定義與資料庫無關的夾具(例如,關於特定檔案和目錄的夾具),您可以從更通用的基底類別 yii\test\Fixture 擴充,並覆寫 load() 和 unload() 方法。
如果您正在使用 Codeception 來測試您的程式碼,您可以使用內建的支援來載入和存取夾具。
如果您正在使用其他測試框架,您可以在您的測試案例中使用 yii\test\FixtureTrait 來達到相同的目標。
在下面,我們將描述如何使用 Codeception 編寫 UserProfile
單元測試類別。
在您的擴充 \Codeception\Test\Unit
的單元測試類別中,宣告您想要在 _fixtures()
方法中使用的夾具,或直接使用 actor 的 haveFixtures()
方法。例如,
namespace app\tests\unit\models;
use app\tests\fixtures\UserProfileFixture;
class UserProfileTest extends \Codeception\Test\Unit
{
public function _fixtures()
{
return [
'profiles' => [
'class' => UserProfileFixture::class,
// fixture data located in tests/_data/user.php
'dataFile' => codecept_data_dir() . 'user.php'
],
];
}
// ...test methods...
}
_fixtures()
方法中列出的夾具將在執行測試之前自動載入。正如我們之前描述的,當夾具正在載入時,它的所有依賴夾具將首先自動載入。在上面的範例中,由於 UserProfileFixture
依賴於 UserFixture
,因此當在測試類別中執行任何測試方法時,將依序載入兩個夾具:UserFixture
和 UserProfileFixture
。
當為 _fixtures()
和 haveFixtures()
指定夾具時,您可以使用類別名稱或組態陣列來引用夾具。組態陣列將讓您在載入夾具時自訂夾具屬性。
您也可以為夾具指派別名。在上面的範例中,UserProfileFixture
被別名為 profiles
。在測試方法中,您可以接著在 grabFixture()
方法中使用其別名來存取夾具物件。例如,
$profile = $I->grabFixture('profiles');
將傳回 UserProfileFixture
物件。
由於 UserProfileFixture
從 ActiveFixture
擴充,您可以進一步使用以下語法來存取夾具提供的資料
// returns the UserProfile model corresponding to the data row aliased as 'user1'
$profile = $I->grabFixture('profiles', 'user1');
// traverse data in the fixture
foreach ($I->grabFixture('profiles') as $profile) ...
預設情況下,夾具類別會在 data
資料夾下尋找相應的資料檔案,該資料夾是包含夾具類別檔案的資料夾的子資料夾。當您處理簡單的專案時,可以遵循此慣例。對於大型專案,您可能經常需要為不同測試的相同夾具類別切換不同的資料檔案。因此,我們建議您以類似於您的類別命名空間的階層方式組織資料檔案。例如,
# under folder tests\unit\fixtures
data\
components\
fixture_data_file1.php
fixture_data_file2.php
...
fixture_data_fileN.php
models\
fixture_data_file1.php
fixture_data_file2.php
...
fixture_data_fileN.php
# and so on
透過這種方式,您將避免測試之間夾具資料檔案的衝突,並根據需要使用它們。
注意:在上面的範例中,夾具檔案的命名僅用於範例目的。在現實生活中,您應該根據您的夾具類別擴充自哪個夾具類別來命名它們。例如,如果您從 yii\test\ActiveFixture 擴充用於資料庫夾具,則應使用資料庫表名稱作為夾具資料檔案名稱;如果您從 yii\mongodb\ActiveFixture 擴充用於 MongoDB 夾具,則應使用集合名稱作為檔案名稱。
可以使用類似的階層來組織夾具類別檔案。您可以想要使用 fixtures
作為根目錄,而不是使用 data
作為根目錄,以避免與資料檔案衝突。
yii fixture
管理夾具 ¶Yii 透過 yii fixture
命令列工具支援夾具。此工具支援
假設我們有夾具資料要載入
#users.php file under fixtures data path, by default @tests\unit\fixtures\data
return [
[
'name' => 'Chase',
'login' => 'lmayert',
'email' => 'strosin.vernice@jerde.com',
'auth_key' => 'K3nF70it7tzNsHddEiq0BZ0i-OU8S3xV',
'password' => '$2y$13$WSyE5hHsG1rWN2jV8LRHzubilrCLI5Ev/iK0r3jRuwQEs2ldRu.a2',
],
[
'name' => 'Celestine',
'login' => 'napoleon69',
'email' => 'aileen.barton@heaneyschumm.com',
'auth_key' => 'dZlXsVnIDgIzFgX4EduAqkEPuphhOh9q',
'password' => '$2y$13$kkgpvJ8lnjKo8RuoR30ay.RjDf15bMcHIF7Vz1zz/6viYG5xJExU6',
],
];
如果我們正在使用將資料載入資料庫的夾具,那麼這些列將應用於 users
表。如果我們正在使用 nosql 夾具,例如 mongodb
夾具,那麼這些資料將應用於 users
mongodb 集合。為了了解有關實作各種載入策略以及更多資訊,請參閱官方 文件。上面的夾具範例是由 yii2-faker
擴充套件自動產生的,請在這些 章節 中閱讀更多相關資訊。夾具類別名稱不應為複數。
夾具類別應以 Fixture
作為後綴。預設情況下,夾具將在 tests\unit\fixtures
命名空間下搜尋,您可以使用組態或命令選項來變更此行為。您可以透過在名稱前指定 -
來排除某些夾具,例如 -User
,以進行載入或卸載。
要載入夾具,請執行以下命令
注意:在載入資料之前,會執行卸載順序。通常,這會導致清除先前夾具執行插入的所有現有資料。
yii fixture/load <fixture_name>
必要的 fixture_name
參數指定將載入資料的夾具名稱。您可以一次載入多個夾具。以下是此命令的正確格式
// load `User` fixture
yii fixture/load User
// same as above, because default action of "fixture" command is "load"
yii fixture User
// load several fixtures
yii fixture "User, UserProfile"
// load all fixtures
yii fixture/load "*"
// same as above
yii fixture "*"
// load all fixtures except ones
yii fixture "*, -DoNotLoadThisOne"
// load fixtures, but search them in different namespace. By default namespace is: tests\unit\fixtures.
yii fixture User --namespace='alias\my\custom\namespace'
// load global fixture `some\name\space\CustomFixture` before other fixtures will be loaded.
// By default this option is set to `InitDbFixture` to disable/enable integrity checks. You can specify several
// global fixtures separated by comma.
yii fixture User --globalFixtures='some\name\space\Custom'
要卸載夾具,請執行以下命令
// unload Users fixture, by default it will clear fixture storage (for example "users" table, or "users" collection if this is mongodb fixture).
yii fixture/unload User
// Unload several fixtures
yii fixture/unload "User, UserProfile"
// unload all fixtures
yii fixture/unload "*"
// unload all fixtures except ones
yii fixture/unload "*, -DoNotUnloadThisOne"
類似的命令選項,例如:namespace
、globalFixtures
也可以應用於此命令。
雖然命令列選項允許我們即時設定夾具命令,但有時我們可能想要一次性設定命令。例如,您可以如下設定不同的夾具路徑
'controllerMap' => [
'fixture' => [
'class' => 'yii\console\controllers\FixtureController',
'namespace' => 'myalias\some\custom\namespace',
'globalFixtures' => [
'some\name\space\Foo',
'other\name\space\Bar'
],
],
]
Yii 也可以根據某些範本為您自動產生夾具。您可以使用不同的語言和格式產生具有不同資料的夾具。此功能由 Faker 函式庫和 yii2-faker
擴充套件完成。請參閱擴充套件 指南 以取得更多文件。
在上面,我們描述了如何定義和使用夾具。下面我們總結了執行資料庫相關單元測試的典型工作流程
yii migrate
工具將您的測試資料庫升級到最新版本;發現錯字或您認為此頁面需要改進?
在 github 上編輯 !
註冊 或 登入 以發表評論。