前言
本文為《現代 PHP》一書的學習筆記。
環境
- Windows 10
- Wnmp 3.1.0
測試
許多 PHP 開發者將測試視為不必要且浪費時間的行為,而且現存太多的測試工具,有著不易上手的學習曲線。但其實測試是一個會發生在應用程式開發流程的開始、中途和結束的程序。
為何要做測試
測試可以幫助開發者在第一時間就運作良好的程式,不需要在未來浪費無數小時來為程式除錯並重構。
何時要做測試
測試是一個在開發前、開發中、開發後都存在的議題,敷衍地建立幾個測試並且通過它,這是錯誤的行為。
開發前:安裝並部署測試工具。
開發中:建立應用程式中的每個部分時,都撰寫測試並執行測試。
開發後:持續性地修正並改良測試,就像應用程式本身一樣。
測試什麼
獨立地測試應用程式中最小的區塊,如每個類別、方法和函式,以確保他們如預期執行,這種測試稱為「單元測試」。
但測試區塊並不能保證整個應用程式都能如期運作,因此還需要利用自動化的工具測試應用程式高層級的行為,這種測試稱為「功能測試」。
如何測試
PHP 開發者使用了幾種熱門的方式進行測試,他們之間並不互斥。
單元測試
單元測試是最熱門的,現在標準的 PHP 單元測試框架為由 Sebastian Bergmann 所撰寫的 PHPUnit。
測試驅動開發(TDD)
測試驅動開發(Test-driven development)是在撰寫程式碼之前先撰寫測試,這些測試會故意失敗,因為它描述了應用程式應當擁有的行為。
TDD 不停重複「撰寫測試並建立功能」的這個過程,直到應用程式完成為止。
行為驅動開發(BDD)
行為驅動開發(Behavior-driven development)有兩種形式:SpecBDD 和 StoryBDD。
BDD 使用流暢的人性化語言來描述應用程式的實作層面,SpecBDD 測試以開發者的角度組合事情,而 StoryBDD 以專案管理者的角度組合事情,他們經常被一起使用。
PHPUnit
PHPUnit 測試會集合成測試案例,測試案例會集合成測試程序,PHPUnit 會使用測試執行器來進行測試。
每個案例都包含了名稱以 test
為前綴的公開方法,這些方法是獨立的測試,用來測試特別的情況是否如預期執行。
一個測試類別通常以
Test
結尾。
初始的 PHPUnit 測試執行器是命令列執行器,可以在終端機使用 phpunit
指令來觸發。
目錄架構
範例的目錄架構如下:
1 | |- src/ |
src
目錄包含 PHP 專案的原始碼。tests
目錄包含 PHP 專案的 PHPUnit 測試,其中的bootstrap.php
檔在單元測試執行前,會由 PHPUnit 所匯入。composer.json
列出 Composer 所管理的相依性元件。phpunit.xml
提供 PHPUnit 測試執行器的設定細節。.travis.yml
提供 Travis CI 持續測試網頁服務所需要的設定細節。
啟用 Xdebug
Xdebug 剖析器可以用來產生有用的程式碼覆蓋率資訊。
如果是在 Wnmp
的環境,打開 php.ini
檔並取消以下註解以啟用 Xdebug PHP 擴充。
1 | ;zend_extension=php_xdebug.dll |
安裝 PHPUnit
Composer 是安裝 PHPUnit 測試框架最方便的方式之一。
1 | composer require --dev phpunit/phpunit |
配置 PHPUnit
在專案的 phpunit.xml
檔中配置 PHPUnit。
1 |
|
<phpunit>
根元素的屬性是 PHPUnit 測試執行器的設定,最重要的設定是bootstrap
設定,它指明在 PHPUnit 測試執行前,會被匯入的 PHP 檔案路徑。<testsuites>
元素定義tests
資料夾中,以Test.php
結尾的檔案將被 PHPUnit 執行。<filter>
元素列出所有包含在程式碼覆蓋率檢測中的目錄。<whitelist>
元素告訴 PHPUnit 只要針對src
目錄進行程式碼覆蓋率檢測。
實作
假想一個 Whovian
類別作為測試範例。
範例 10-1:Whovian
類別
1 | class Whovian |
每個測試案例都需要繼承 PHPUnit_Framework_TestCase
類別。
範例 10-2:WhovianTest
測試案例
1 |
|
assertAttributeEquals()
方法斷言預期的値與指定物件的屬性的値相同。assertEquals()
方法斷言預期的値與結果的値相同。
執行測試
打開終端機,進入專案的最上層目錄,使用以下指令啟動 PHPUnit 測試執行器。
1 | vendor/bin/phpunit -c phpunit.xml |
-c
或--configuration
選項可以使用不同的設定檔。
程式碼覆蓋率
PHPUnit 的程式碼覆蓋率報表,可以觀看哪些程式碼被測試(或未被測試)。
使用以下指令生成報表。
1 | vendor/bin/phpunit -c phpunit.xml --coverage-html coverage |
--coverage-html
的値代表存放報表的資料夾路徑。
接著,在 http://localhost/php/modern-php/10-testing/coverage/ 可以查看報表。
通常 100% 的覆蓋率是不切實際的,覆蓋率多寡的程度根據每個專案而有所不同。
Travic CI
測試應當自動化執行,Travic CI 是很好的持續測試網頁服務,因為它可以原生地和 GitHub 儲存庫結合。
前往 Travic CI,以 GitHub 帳戶登入,選擇要測試的儲存庫。
範例的 .travis.yml
檔如下:
1 | language: php |
language
是應用程式所使用的語言。php
是 Travic CI 要測試應用程式的 PHP 版本。before_script
是在 Travic CI 要測試應用程式之前會執行的指令。script
是在 Travic CI 要測試應用程式時執行的指令。notification
是通知的相關設定。
執行
每次提交新的程式碼到 GitHub 儲存庫時,Travic CI 會自動執行應用程式測試,並將測試結果以電子郵件通知。