在這裡總結的許多編程慣用法都是很值得做為單獨一個章節的甚至一本書的你應該把這章做為PHP模式設計使用慣用法的相關介紹而且查看一些列出的參考書來進行更深入的學習
測試你的代碼
可能沒有什麼代碼慣用法比測試代碼更加重要了好的測試可以提高開發速度
可能一開始這句格言會和你的直覺相矛盾你可能會斷言測試是自由的障礙物事實上恰恰相反如果你十分完整的運行那些測試來檢查你的軟件的公共接口你就可能在不改變(或者更加糟糕破壞)原來的應用軟件的前提下改變自己系統內在的執行測試並檢驗你的公共接口的精確性和正確性並且讓自己隨意改變一些代碼的內在工作來確保你的軟件是正確而且沒有bug(錯誤)
在討論更多關於測試的好處之前先讓我們看一個示例這本書裡面所有的測試實例都使用了PHP測試框架——SimpleTest 這個測試框架可以在 ;獲取到
考慮下面的代碼
<?php
// PHP
// the subject code
define(TAX_RATE );
function calculate_sales_tax($amount) {
round($amount * TAX_RATE);
}
// include test library
require_once simpletest/unit_testerphp;
require_once simpletest/reporterphp;
// the test
class TestingTestCase extends UnitTestCase {
function TestingTestCase($name=) {
$this>UnitTestCase($name);
}
function TestSalesTax() {
$this>assertEqual( calculate_sales_tax());
}
}
// run the test
$test = new TestingTestCase(Testing Unit Test);
$test>run(new HtmlReporter());
上面的代碼首先定義了一個常量——TAX_RATE和一個計算銷售稅的函數接著代碼包含了使用SimpleTest框架的必備組件單體測試本身和一個用來顯示測試結果的reporter模塊
類TestingTestCase繼承於SimpleTest框架的UnitTestCase類通過擴展UnitTestCase類TestingTestCase裡面所有使用Test開頭的方法都將被認為是測試實例——創造條件來調試你的代碼並斷言結果
TestingTestCase定義了一個測試TestSalesTax()它包含了一個斷言函數AssertEqual()如果它的前兩個輸入參數是相等的它將返回true否則返回false(如果你想顯示assertEqual()失敗的信息你可以傳入三個參數就像這樣$this>assertEqual(calculate_sales_tax() The sales tax calculation failed))
代碼的最後兩行創建了這個測試實例的實體並且使用一個HtmlReporter運行了它你可以訪問這個web頁面來運行這個簡單的測試
運行這個測試將顯示測試名稱失敗斷言的詳細情況和一個總結條(綠色的意味著成功(所有的斷言都通過了)而紅色的暗示著失敗(至少有一個斷言沒有通過))
(assertion(斷言)在軟件開發中是一種常用的調試方式很多開發語言中都支持這種機制在實現中assertion就是在程序中的一條語句它對一個boolean表達式進行檢查一個正確程序必須保證這個boolean表達式的值為true如果該值為false說明程序已經處於不正確的狀態下系統將給出警告或退出一般來說assertion用於保證程序最基本關鍵的正確性assertion檢查通常在開發和測試時開啟為了提高性能在軟件發布後assertion檢查通常是關閉的)
注(assertion(斷言)在軟件開發中是一種常用的調試方式很多開發語言中都支持這種機制在實現中assertion就是在程序中的一條語句它對一個boolean表達式進行檢查一個正確程序必須保證這個boolean表達式的值為true如果該值為false說明程序已經處於不正確的狀態下系統將給出警告或退出一般來說assertion用於保證程序最基本關鍵的正確性assertion檢查通常在開發和測試時開啟為了提高性能在軟件發布後assertion檢查通常是關閉的)
上面的代碼有一個(有意的)錯誤所以運行是不能通過了顯示結果如下
Calculate_sales_tax()這麼一個簡單的才一行的函數哪裡出錯了呢?你可能已經注意到這個函數沒有返回結果下面是正確的函數
function calculate_sales_tax($amount) {
return round($amount * TAX_RATE);
}
修改後運行測試通過
但是一個簡單的測試並不能保證代碼是穩定的比如你把calculate_sales_tax()改成 function calculate_sales_tax($amount) { return ; }代碼也會通過測試但只有當美元等價於的時候才是正確的你可以自己增加一些額外的測試方法來測試其他的靜態值
function TestSomeMoreSalesTax() {
$this>assertEqual( calculate_sales_tax());
}
或者改變函數TestSalesTax()來驗證第二個(和第三個等等)值如下所示
function TestSalesTax() {
$this>assertEqual( calculate_sales_tax());
$this>assertEqual( calculate_sales_tax());
}
到目前為止還有一種更好的方法就是新增加一個測試選擇隨即值來測試你的代碼具體如下
function TestRandomValuesSalesTax() {
$amount = rand();
$this>assertTrue(defined(TAX_RATE));
$tax = round($amount*TAX_RATE*)/;
$this>assertEqual($tax calculate_sales_tax($amount));
}
TestRandomValuesSalesTax()引入了方法assertTrue()如果傳入的第一個變量等於於布爾真則assertTrue()通過(和方法assertEqual()一樣方法assertTrue()在接受一個可選擇性的額外的後將返回一個失敗的信息)所以TestRandomValuesSalesTax()首先認為常量TAX_RATE已經定義了然後使用這個常量來計算隨機選擇的的數量的稅收
但是TestRandomValuesSalesTax()也存在一個問題它很大程度的依賴於方法calculate_sales_tax()測試是應該和特殊的實現細節無關的一個更好的測試應該只建立一個合理的分界線接下來的這個測試假定銷售稅永遠不會超過%
function TestRandomValuesSalesTax() {
$amount = rand();
$this>assertTrue(calculate_sales_tax($amount)<$amount*);
}
確保你的代碼正常工作是測試的首要的目的但是在測試你的代碼時候你應該認識到除此之外還有一些額外的相對次要的目的
測試讓你書寫容易測試的代碼
這使得代碼松散耦合
復雜設計
而且具有很好的模塊性
測試能讓你清晰的了解運行代碼的期望結果
讓你從一開始就注重於模塊的設計和分析
通過測試
也會讓你考慮所有可能的輸入和相應的輸出結果
測試能很快速的了解編碼的目的
換句話說
測試事例扮演著
實例
和
文檔
的功能
准確的展示著如何構建一個類
方法等
在這本書中
我有時候通過一個測試事例來演示代碼的期望功能
通過讀取一個測試方法的聲明
你可以清楚的了解代碼是如何運行的
一個測試實例定義在代碼在明確慣用法下的運行情況
最後如果你的測試集——測試實例的集合——是非常徹底的而且當所有的測試都通過的時候你可以說你的代碼是完備的有趣的是這個觀點也恰好是Test Driven Development(測試驅動開發)的特征之一
Test Driven Development(TDD)也被認為是Test First Coding(編碼前測試)Test First Coding是一種把測試更提前一步的方法在你寫任何代碼之前先寫好測試你可以從下載到一份很好的簡潔的關於TDD的摘要文章同時下載到一本很好的關於策略的入門書——Kent Beck著作的《Test Driven DevelopmentBy Example》(這本書的例子都是用JAVA開發的但其中代碼的可讀性是很好的而且對主題的介紹和說明都做的很好的)
注敏捷開發(Agile Development)
最近單體測試——特別是測繪驅動開發——已經和敏捷開發方法學緊密的聯系起來了比如說極限編程(XP)極限編程的焦點關注於快速的反復的發步功能性的代碼給客戶並把變化的客戶需求做為開發過程中的必備部分下面是一些關於學習敏捷編程的在線資源
函數性測試
這本書裡面的大部分測試例子都是用來測試面對對象的代碼但是所有形式的編程都可以從中得到收獲的單體測試框架比如說PHPUnits和SimpleTest也都能很容易的用來測試功能函數的例如上面的SimpleTest例子它就是用來測試calculate_sales_tax()函數的世界各地的程序員們把單體測試用例放到你的函數庫裡面吧!
我希望經過上面的討論後你也會被帶動起來——測試引導(Test Infected)!(這個術語原創於Erich Gamma詳細情況請見文章)就象Gamma所寫的那樣剛開始你可能會感到測試是很繁瑣的但是當你為你的程序搭建好一個廣闊的測試集後你將你的代碼更加自信!
From:http://tw.wingwit.com/Article/program/PHP/201405/30957.html