今天要來繼續修改昨天建置資料庫的部分,有太多需要人工處理的步驟,期望讓幾乎全部都能自動化。
4c
。Laravel 5.5 新增了 RefreshDatabase trait [1],用途是在測試時將資料表內容清空。
在測試類別中 use RefreshDatabase
,該類別的所有測試函數,每一次的前與後都會先清空表格,確保每個測試函數都能有相同的起始條件。
同時 RefreshDatabase 還會自動幫忙把空的資料庫 migrate 到最新的狀態,省掉了手動 migrate 的步驟。
理所當然在加入這行程式後,對昨天的程式碼執行測試會變得不通過,因為昨天的那筆 "Hello, I'm Louis." 是我們手動加入的,此時就被 RefreshDatabase 刪掉了。
資料表現在已經會透過 RefreshDatabase 自動 migrate 產生了,但是資料庫的檔案並不會。
所以我們的 sqlite 檔案依舊先手動建立:
$ sqlite3 database/database.sqlite
由於 .env 應該是要存放著供產品階段使用的環境設定,因此來把 sqlite 改成只在測試時會使用。
在 <php>
中加入 <env>
來加入,同時 force
參數是代表會覆寫,預設則是會優先使用 .env 已有的設定。
<php>
<env name="DB_CONNECTION" value="sqlite" force="true"/>
<env name="DB_DATABASE" value="database/database.sqlite" force="true" />
</php>
現在即使把昨天在 .env 中刪掉的部分加回去,測試時也可以正常運作了。
Factory 模型工廠,是用來產生假的 Model instance,昨天在利用 artisan 建立 Model 檔案時,其中的 -f 參數就是代表同時也建立相對應的 Factory 函式的檔案。
還可以搭配 Faker 自動生成假資料,不過先一步一步來。
<?php
use App\Post;
$factory->define(Post::class, function () {
return [
'post_text' => "Hello, I'm Louis."
];
});
由於產品程式已經在前一天寫完了,說是 TDD 的紅燈,不如說是 Refactor 重構,來的更適合。
class PostTest extends TestCase
{
use RefreshDatabase;
public function testInsertPost()
{
$post = factory(Post::class)->create();
$this->assertDatabaseHas('posts', [
'post_text' => "Hello, I'm Louis."
]);
}
}
利用 factory 及 create() 來創建 $post 並加入這筆資料。
接著發現 testInsertPost 通過了,但是 testAllPost 卻沒通過。
testAllPost 會無法通過的原因,是我們剛剛加入的 use RefreshDatabase;
,資料表每個測試函數的前後都會清空。
所以我們也在這裡使用 factory 來加入一筆資料。
class PostTest extends TestCase
{
use RefreshDatabase;
public function testAllPost()
{
$post = factory(Post::class)->create();
$response = $this->get('/posts/');
$response->assertStatus(200);
$response->assertSee('All Posts:');
$response->assertSee("Hello, I'm Louis.");
}
}
( $ git checkout 4c
)
終於不需要再手動進行那麼多步驟了!只剩下唯一的一步:自動建立測試用的資料庫,讓明天的我來接棒。
interface
,使用方法是在類別中 use some_trait
,並且跟 namespace 的 use
是不同的語法。