導入驗收測試(一)
導入 Composer 的時候,我們有新增一個範例的單元測試。如果可以的話,下一步當然就是開始寫一些基本的單元測試,來保護系統元件。但,並不是每個專案都能這麼開心,如果真的無法寫單元測試的話該怎麼辦呢?沒關係,我們還能寫驗收測試!
HTTP Tests
Laravel 的測試套件相當完整,HTTP Tests 是 Laravel 測 HTML 的說明文件。
我們先試著修改 tests/Feature/ExampleTest.php
,寫看看首頁的測試:
class ExampleTest extends TestCase |
接著跑測試:
$ php vendor/bin/phpunit |
這裡大家可以試著做一件事:把 Server 關掉,再跑一次測試看看。
大家會發現,其實測試還是能正常執行的。這是因為 Laravel 把輸出頁面的方法,包成了物件,直到 route 處理到某個階段的時候,才輸出網頁;Laravel 的測試則是在輸出到網頁前,把物件擋下來然後拿來當字串(HTML)驗證。
這個做法好處當然很多,最大的好處是:只要能跑 PHP,不需要起伺服器就能執行測試。這執行測試的機會變得更大(因為需要的條件變少了);同樣的,不起伺服器,就少了非常多傳輸成本,速度肯定是更快的。
有一好沒兩好,它的壞處就是無法完全模擬真實的環境,包括 HTTP Server 或是瀏覽器執行 Javascript 等。除此之外,因為會使用一個 process 執行所有測試,這代表所有測試的記憶體是共享的,那就得小心單例模式全域影響的問題或是自動載入的問題等。
首頁測好了,那我們來測看看管理頁:
/** |
但它會發生錯誤:
1) Tests\Feature\ExampleTest::shouldBeOkWhenSeeAdminPage |
它說「預期會拿到 status code 200 但事實上拿到了 404 」,這很有可能是因為我們 Route 並沒有設定好,來調整一下 routes/web.php
:
// 忘了在後面加 .php |
這裡調整完後,會發生很杯具的錯誤:
1) Tests\Feature\ExampleTest::shouldBeOkWhenSeeAdminPage |
它說「預期會拿到 status code 200 但事實上拿到了 404 」,查了一下 log,它說找不到 tpl 這個變數:
Undefined variable: tpl at /Users/miles.chou/GitHub/MilesChou/book-refactoring-30-days/admin.php:194 |
往源頭找 $tpl
是在 config.php
設定的,找不到代表沒有載入過。這正是前面有提到的「自動載入」問題,因為 config.php
曾被 require 過,所以這裡就不會再 require 了,才會找不到變數。最簡單的解法是:把 require_once
改成 require
,不過十之八九都有可能出事,就先試看看。
改完跑完之後,出現別的錯誤了:
DEBUG_MODE already defined at /Users/miles.chou/GitHub/MilesChou/book-refactoring-30-days/config.php:14 |
這昨天有提到解法如下:
defined('DEBUG_MODE') or define('DEBUG_MODE', env('APP_DEBUG')); |
後面也有許多類似的錯誤都一起解掉,再跑一次應該就會過了。
今天成功把基本的驗收測試加上去了,明天我們再換跑瀏覽器的測試。
程式碼可以參考 GitHub PR