本文將帶領讀者建立 CodeIgniter 3 框架的 PHPUnit 測試環境,給 CodeIgniter 3 一個現代化的機會!
本文假設您已經具備 軟體測試自動化 以及 PHPUnit 相關知識,且了解如何撰寫測試案例。若您尚未了解單元測試或軟體測試自動化,這裡提供一些不錯的資源讓您初步了解:
除了上面兩個資源外,請您務必花時間認識並學習軟體測試,這可以說是軟體開發技術的核心技能之一。
若您尚未了解 PHPUnit 這裡也有些簡單的文件供您參考:
前言
2020 年對於 PHP 界風靡一時的 MVC 框架「CodeIgniter」來說,光環已經被新星 Laravel 搶去。雖然 CodeIgniter 的討論熱度已經消退了,但市佔率仍然相當高,至今仍有許多 PHPer 還在與 CodeIgniter 奮鬥和成長(包括我)。
由於 CodeIgniter 3 框架(以下簡稱 CI3)沒有使用 Namespace 的特性,加上 CI3 統一透過框架內建的 Loader
類別實現 Autoload 機制,造成很多 PHPer 沒辦法在 CI3 框架中使用現代 PHP 的特性來開發系統。若不做點手腳的話,PHPer 的開發思維很容易就會被 CI3 框架綁架,一不小心就將所有業務邏輯全部寫在 CI3 框架中。換句話說所有的程式碼都依賴於框架,物件導向 SOLID 的實現、設計模式、單元測試都不用談了!
為了讓還在與 CI3 奮鬥的同袍們能夠使用現代 PHP 的特性來開發系統,本文將介紹如何在 CI3 框架中建立單元測試的環境,讓 CI3 也能使用並測試現代 PHP 的程式碼,確保 PHPer 能安心地實現各種開發策略和思維。
導入 Composer 擁抱現代 PHP 特性
其實 CI3 跟現代 PHP 只差臨門一腳,你可以在 config/Config.php 中找到一個設定為 composer_autoload
,只要替 composer_autoload
設定 Composer 目錄底下的 autoload.php 路徑,你的 CI3 框架就可以開始使用 Namespace 搭配 PSR-4 Autoload 機制來開發現代 PHP 特性的程式碼!
編輯 application/config/config.php:
1 | /* |
安裝 ci-phpunit-test
由於 CI3 架構內建的單元測試功能很少,所以我選用整合了 PHPUnit 的 ci-phpunit-test 來當作專案的測試框架。
ci-phpunit-test 除了包含 PHPUnit 測試框架本身的功能以外,還提供模擬 HTTP Request 的整合測試功能,重構前建立回歸測試來說相當方便!不過使用這個套件之前,有一些必要條件:
- PHP 版本至少高於 5.4.0
- CodeIgniter 至少要有 3.0
- 至少要安裝 PHPUnit 4.3 以上的版本
透過 Composer 下載 ci-phpunit-test
到你的專案目錄下使用 Composer 下載 ci-phpunit-test
1 | $ cd /path/to/codeigniter/ |
透過 install.php 安裝 ci-phpunit-test
下載完成後,需要執行一次 install.php
注意,必須要在專案的根目錄執行安裝指令
安裝指令每次都會建立並覆蓋整個 application/tests 目錄
1 | $ cd /path/to/codeigniter/ |
安裝完成後,application 目錄下會出現 tests 目錄,以後測試程式都要放在這個 tests 目錄底下:
1 | codeigniter/ |
第一次執行 ci-phpunit-test
在執行 ci-phpunit-test 之前,一定要確保兩件事:
(以下為 OSX 系統安裝 PHPUnit 步驟)
1 | $ wget https://phar.phpunit.de/phpunit-7.0.phar |
這麼做是因為 ci-phpunit-test 要求一定要在 application/tests
目錄執行 phpunit
:
1 | $ cd /path/to/codeigniter/ |
撰寫測試案例:
到目前為止,你的 CI3 框架已經完全整合了 PHPUnit,並且可以利用 Composer 的 Autoload 機制引入使用現代 PHP 特性的受測程式碼。但是本篇主題是建立測試環境,若還想知道更多測試案例的寫法,可以直接參考 ci-phpunit-test 作者提供的線上手冊:How to Write Tests 和電子書 CodeIgniter Testing Guide。
我也會陸續新增幾篇 CodeIgniter 撰寫整合測試、單元測試的文章供大家參考。
CI3 + HMVC 測試環境配置
因為 CodeIgniter + HMVC 的結構較為特殊,安裝 ci-phpunit-test 之後還需手動做一些修改,才能在 HMVC 的環境中執行ci-phpunit-test 測試框架。
接下來的修改是參考 ci-phpunit-test 作者針對 Github issue 34:Any luck with ci-phpunit-test working with HMVC? 的回應,對 CI3 做調整。這些調整的目的是改變 CI3 載入 HMVC 套件的順序,讓測試環境取得 HMVC 的物件,而不是原生 CI 的物件。
步驟一:修改 Modules.php
編輯 ci/application/third_party/MX/Modules.php:
1 | <?php (defined('BASEPATH')) OR exit('No direct script access allowed'); |
步驟二:修改 Loader.php
編輯 ci/application/third_party/MX/Loader.php:
1 | public function initialize($controller = NULL) |
步驟三:設定 PHPUnit 預設設定檔案
在執行 ci-phpunit-test 之前,記得要將 PHPUnit 的設定檔案預設為:
1 | ci/application/tests/phpunit.xml |
否則 ci-phpunit-test 會因為沒載入 Autoload 而無法順利執行。
注意事項
禁止使用 header() 跳頁
整合測試中,ci-phpunit-test 只接受 CI3 的 Output 類別輸出結果,若在程式運行中途對 header 設定做任何修改,測試框架將會出現錯誤訊息。為了讓測試案例可以運作,應盡量在系統中使用 CI3 內建的 redirect 進行轉址,若沒辦法避免使用 header()
,也可以用 ENVIRONMENT 環境變數進行跳脫。
1 | -header('Location: ' . base_url(). 'admin'); |
推薦安裝:Codeception\Specify
Codeception\Specify 供測試環境使用 BDD 語法。
Codeception\Specify 可以在測試案例中隔離測試情境,減少很多因為情境產生的測試 function。
透過 Composer 安裝 Codeception\Specify
1 | $ composer require codeception/specify |
使用方法:直接在測試程式中引入 Codeception\Specify
Trait:
1 | <?php |
使用範例:簡化多個測試案例情境
結尾
這篇文章其實「CodeIgniter 3 單元測試日常」系列文的揭幕,這系列文的目的除了分享經驗以外,也想讓更多仍在維護 CodeIgniter 框架(或非現代 PHP 框架)的開發人員知道,原來手頭上的框架也可以變得現代化!希望可以給維護舊框架的開發人員帶來一絲希望,不要被舊框架或專案嚇跑了!