寫到今天進入第十九天,看來離完賽已不遠矣?
最近幾天寫到有點厭世,感覺自己其實沒有想像中有料(?),畢竟工作經驗不是非常的多,因此很多原本想講題目的也怕自己不夠了解,講不出重點,不過既然報名的組別是鐵人賽的自我挑戰組,這也是一種挑戰自我的方式吧?
看看目前的發文跟第一天規劃的大綱有什麼差別,結論是雖然有經過整理,但相較其他完整的應用方式仍過於零散,這也許是之後可以改進的地方,不過到目前為止,算是把我在 Laravel 的應用整理出基本的脈絡了,不過身為一個軟體工程師,不斷的自我學習本來就是必備的職能,繼續努力吧!
今天我們來講 Laravel 的測試,撰寫測試我認為是一個大型系統或應用上線時必須具備的功能,小型的系統或專案也許功能不多,因此可以透過一些簡單的手動測試便可找出 bug,但當你的系統功能越來越多,且不同功能之間也許會有相依性,這時需要的測試範疇越來越廣,就需要透過程式進行自動化測試,除此之外,如果我們每次在系統上線前都需要再手動測試之前開發過的功能,也會浪費不少時間,透過自動化測試,能夠讓我們直接測試舊有功能,因為他能夠幫助你找到程式可能會出錯的地方,也能夠確保未來在不同環境中能否正常運行。
Laravel 也有將 PHPUnit 放在裡面,PHPUnit 是一套協助測試 PHP 程式碼的測試框架,
phpunit.xml
是 PHPUnit 的設定檔,一般都需要在裡面設定跑測試的資料夾路徑,但 Laravel 都已經寫設定完畢,因此不太需要更動到太多的設定。vendor/
執行 PHPUnit,也能夠透過 Laravel Artisan 提供的指令執行./vendor/bin/phpunit
# or
php artisan test
如果我們的系統已開發好會員的註冊功能,我們可以寫入自動化測試中,之後開發新功能時不用再次測試這個地方,如果你設計的其他功能與這邊有關聯或是依賴性,導致錯誤的話,自動化測試也可以幫你找到錯誤。
一般來說,測試的時候不會使用正式資料庫進行測試,否則可能會造成正式環境的錯誤
因此在 config/database.php
內的 connection
內增加以下內容
'sqlite_testing'=>[
'driver'=>'sqlite',
'database'=>':memory:',
'prefix'=>'',
'foreign_key_constraints'=>true,
],
※註:PHPUnit 的 driver 使用 sqlite,database 則在記憶體內跑,可以大幅提升測試效率
在 phpunit.xml
建立前一步驟的 DB_CONNECTION 以及其他參數
<php>
<server name="APP_ENV" value="testing"/>
<server name="BCRYPT_ROUNDS" value="4"/>
<server name="CACHE_DRIVER" value="array"/>
<server name="DB_CONNECTION" value="sqlite_testing"/>
<server name="DB_DATABASE" value=":memory:"/>
<server name="MAIL_DRIVER" value="array"/>
<server name="QUEUE_CONNECTION" value="sync"/>
<server name="SESSION_DRIVER" value="array"/>
</php>
建立測試檔案
php artisan make:test RegisterTest
※註:PHPUnit 的檔案結尾強制使用 Test.php
測試註冊頁面,首先先列出目前被啟用的 API
php artisan route:list
再來則至 tests\Feature\RegisterTest.php
內新增以下程式碼
public function testExample()
{
$response = $this->get('/');
$response->assertStatus(200);
}
再來則測試註冊功能,需先了解系統的註冊流程為何
由於每一次測試的時候都會需要新增資料,使用 use RefreshDatabase;
可以在每一次跑測試的時候刷新資料庫。 assert
是 PHPUnit 的斷言方法,詳細使用可以參照 官網文件。
以註冊流程為例,Test 可以這樣寫
use RefreshDatabase;
public function testRegisterPage()
{
$user = factory(User::class)->create();
$this->post('/signup',[
'email'=>$user->email,
'password'=>'password',
'password_confirmation' => 'password',
]);
$this->assertDatabaseHas('users',[
'email'=>$user->email,
]);
$this->assertTrue(
Hash::check('password', User::where('email', $user->email)->first()->password)
);
}
進行測試
./vendor/bin/phpunit
當你的開發越來越大,功能越來越多,到一個程度時我們需要以覆蓋率(Coverage)來確保許多必須被測試到的程式都有順利測試。
你可以到 phpunit.xml
的 testsuites
後加入以下的設定,這樣在每一次執行測試後,就可以到 report 內的 index.html
看你整個程式的測試覆蓋率了。
<logging>
<log type="coverage-html"
target="/path/to/report"
lowUpperBound="35"
highLowerBound="70" />
</logging>
但是這邊必須說,覆蓋率的多寡並不是決定一個系統在測試上的好壞,這必須分清楚,不是一味追求高覆蓋率的測試就是好測試,而是你在這個測試的過程中,是否有測到關鍵的程式碼,這才是需要撰寫自動化測試的原因,否則過度追求高覆蓋率,沒有思考後續各單元的整合性以及關鍵程式碼的測試,很容易導致以下悲劇發生。
但是測試覆蓋率過低,就是沒有好好用心設計系統啦!
明天見!