簡介
單元測試是幾個現代敏捷開發方法的基礎,使得PHPUnit成為許多大型PHP項目的關鍵工具。這個工具也可以被Xdebug擴展用來生成代碼覆蓋率報告 ,並且可以與phing集成來自動測試,最後它還可以和Selenium整合來完成大型的自動化集成測試。
如何部署
方法一: 使用Pear
運行 pear channel-discover pear.;
pear install phpunit/PHPUnit;
方法二 : 手動安裝
1 從官網下載軟體包並解壓
2 把解壓後的目錄加入php.ini中的include_path
3 將腳本pear-phpunit改名為phpunit
4 將phpunit腳本中的@php_bin@替換成php可執行腳本的路徑
5 為phpunit腳本增加可執行許可權並加入$PATH
6 將PHPUnit/Runner/Version.php中的@package_version@替換成3位
PHPUnit版本號
實例測試
要點:
1 編寫的測試用例是一個php腳本
2 require_once 'PHPUnit/Framework.php'是必須的,另外,你需要在測
試用例腳本中包含你需要測試的代碼
3 測試用例的主體必須寫在類中,類名必須和檔案名稱保持一致,還必須是
PHPUnit_Framework_TestCase的子類
4 每一個測試用例都是一個public的成員函式,必須以test開頭
5 程式的輸出使用assert*系列函式來進行驗證
該用例需要在Shell下鍵入phpunit ArrayTest.php來運行。結果如下示:
[username@machine xx]$ phpunit ArrayTest.php
PHPUnit 3.1.3 by Sebastian Bergmann.
..
Time: 0 seconds
OK (2 tests)
結果中最重要的用紅色標出的結果,點號 代表一個用例通過(即assert系列函式都通過)。如果將上面的測試用例testArrayContainsAnElement用例assertEquals函式中的1改為0,則運行結果為:
PHPUnit 3.1.3 by Sebastian Bergmann.
.F
Time: 0 seconds
There was 1 failure:
1) testArrayContainsAnElement(ArrayTest)
FAILURES!
Tests: 2, Failures: 1.
可以很明顯看出結果由原來的 .. 變為 .F ,F表示第二個測試用例未通
過,並且具體與哪一條驗證不符都在後有詳細說明。
除了F外,一個測試用例還有I(未完成),S (跳過),E (錯誤)三種狀態,詳見
準確性
測試用例之間必須保證他們之間是不互相影響的,即這些測試用例無論以任何順序執行,他們的結果都應該一樣。PHPUnit提供了兩個可供重寫的函式來滿足此要求。
成員函式setUp在每一個測試用例開始之前執行,用來創建用於測試的環境。tearDown則在每個測試用例結束時調用,用於還原測試用例對環境帶來的影響。
上示的測試用例中$fixture = array()就可以放在setUp中完成
高級功能
結合XDebug生成代碼覆蓋率報告
如何測試你的測試用例設計,答案是代碼覆蓋率。代碼覆蓋率即當你的
一套測試用例執行完畢時,有多少比例的代碼分支被覆蓋到。
PHPUnit的代碼覆蓋率報告需要另一個優秀的Extension——XDebug
支持。當執行完測試用例後,得出的結果類似
下圖:
圖中綠色高亮的行代表測試用例有覆蓋,紅色相反。而左邊的數字代表
此行代碼被執行過幾次。
代碼覆蓋率報告對指導我們編寫測試用例將有極大的幫助,詳見
結合Phing完成自動化部署
Phing是一個基於Apache Ant的加
快PHP項目部署的工具。當在一個新環境部署PHP項目時,代碼的正確性
不能得到保證,這就需要在部署之前做針對性的測試,只有測試通過整個
過程才能繼續。Phing使用XML檔案定義部署過程,其中測試部分動作可
以使用PHPUnit完成,下面是一個
示例性的部署檔案:
<?xml version="1.0"?>
<project name="BankAccount" basedir="." default="test">
<target name="test">
<phpunit haltonfailure="true" printsummary="true">
<batchtest>
<fileset dir=".">
<include name="*Test.php"/>
</fileset>
</batchtest>
</phpunit>
</target>
</project>
其中需要部署的模組名為BankAccount,動作為test,使用測試工具
為phpunit,所有的測試用例檔案為*Test.php。
如果一切正常,使用Phing部署後可以得到類似下面的結果:
phing
Buildfile: /home/sb/build.xml
BankAccount > test:
[phpunit] Tests run: 4, Failures: 0, Errors: 0, Time elapsed: 0.00067 sec
BUILD FINISHED
Total time: 0.0960 seconds
當然,如果build失敗則你應該根據測試失敗的提示來debug你的程式。
結合Selenium做大型自動化集成測試
前述的測試都是單元測試,測試的輸入都是基於變數和類,而非基於用
戶行為,例如瀏覽器的點擊。在軟體工程定義中,集成測試是在單元測試之
後的更高級別的測試,用PHPUnit作基於瀏覽器的自動化集成測試需要
Selenium的支持。Selenium是一
個完整基於瀏覽器做集成測試的框架。它通過在頁面中嵌入js來模擬用戶
行為。Selenium的經典架構如圖:
可以看出,我們需要一個額外的Selenium Server來負責轉發HTTP請求和執行用戶動作。除此之外,剩下的就是在利用Selenium RC For PHP編寫測試用例。PHPUnit集成了Selenium的API接口,通過直接調用Selenium的API即可完成測試動作和結果驗證,一個典型的測試如下:
可以看出,測試用例書寫方法並沒有很大的,然後在表單q中提交查詢hello world並點擊,最後等待頁面load完畢後校驗新的url中是否包含/Google Search/。
當然,Selenium還提供了更為豐富的API,例如驗證某個表單的值等等。
發展
PHPUnit已經受到了Zend官方和社區的大力支持。最新版本3.1.8已於9月初發布,不僅修正bug,還對mock object,日誌和測試用例框架生成做了更進一步的支持。同時,它也將更容易和PHP的其他優秀工具進行整合來完成更為複雜的任務,詳見:
PHPUnit能給我們帶來什麼?
單元測試在現代軟體開發過程中占據著愈發重要的地位,尤其是敏捷開發。所以,高質量的單元測試是保證項目質量的基礎。
單元測試也為以後的開發提供支緩。就算是開發後期,我們也可以輕鬆的增加功能或更改程式結構,而不用擔心這個過程中會破壞重要的東西。而且它為代碼的重構提供了保障。這樣,我們就可以更自由的對程式進行改進。
同時,編寫單元測試將使我們從調用者觀察、思考。特別是先寫測試(test-first),迫使我們把程式設計成易於調用和可測試的,即迫使我們解除軟體中的耦合。
然後,單元測試是一種無價的文檔,它是展示函式或類如何使用的最佳文檔。這份文檔是可編譯、可運行的,並且它保持最新,永遠與代碼同步。
最後,自動化的單元測試避免了代碼出現回歸,編寫完成之後,可以隨時隨地的快速運行測試。
高效測試
在用PHPUnit做單元測試時,我們可以借鑑先寫測試和測試驅動編碼的思想,將代碼編寫的更加模組化,減少耦合,並且以完成實際功能為目標。這樣的代碼將會有更高的可測性,會大大提高我們的測試效率。
RD利用
1. 利用PHPUnit進行Debug,完成單元自測;
2. 向scm提交測試用例代碼並保持同步;
3. 獲得測試用例的代碼覆蓋率並規定一個閾值(75%?),低於閾值的測試用例不能通過單元測試;
4. 通過QA的反饋改進RD的測試用例;
5. 結合Phing在部署新環境時利用PHPUnit驗證代碼在新環境下的正確性;
6. 結合Selenium做大規模的自動化集成測試,提高提測代碼質量;
另外,按照軟體工程定義的測試用例設計經驗,測試代碼應該是程式代碼量的1.2-1.5倍。雖然初期編寫有一定的代價,但和帶來的效用還是沒有可比性的。
QA利用
1. 通過閱讀RD的測試用例設計來更進一步了解項目設計和功能;
2. 通過QA的角度向RD反饋測試用例設計中的缺陷;
3. 自行編寫測試用例進行測試;
方法一 使用Pear
運行 pear channel-discover pear;
pear install phpunit/PHPUnit
方法二 手動安裝
2. 把解壓後的目錄加入php.ini中的include_path;
3. 將腳本pear-phpunit改名為phpunit;
4. 將phpunit腳本中的@php_bin@替換成php可執行腳本的路徑;
5. 為phpunit腳本增加可執行許可權並加入$PATH;
6. 將PHPUnit/Runner/Version.php中的@package_version@替換成3位PHPUnit版本號。