用phpUnit幫你調(diào)試php程序
邱文宇
| 調(diào)試程序是一個(gè)漫長的過程,程序越長越復(fù)雜,調(diào)試起來就愈加困難。如果你調(diào)試的是php程序,那么不妨采用phpUnit,它可以大大加快你的調(diào)試速度。 |
| Phpunit 脫胎于Fred Yankowski編寫的著名的Junit測試框架。你可以到它的網(wǎng)站 http://www./phiki/phpunit 下載最新的版本。你可以利用phpUnit編寫一套測試軟件包。保證你的程序代碼正確無誤。只需一步便可自動(dòng)完成所有的測試。 |
| 如果監(jiān)測到bug,你就可以再寫一小段測試代碼來找出錯(cuò)誤之所在。日后若再有相同的bug出現(xiàn),只要運(yùn)行你先前的測試包,馬上就可以抓到它。經(jīng)常運(yùn)行測試包便可以保證你的程序代碼的強(qiáng)壯性。 |
| 假設(shè)我們有一個(gè)銀行賬務(wù)處理程序?,F(xiàn)在需要為Account (賬戶) 類編寫一個(gè)測試軟件包。 |
| function Account($initialBalance=0){ |
| $this->balance = $initialBalance; |
| function withdraw($amount){ |
| $this->balance -= $amount; |
| function deposit($amount){ |
| $this->balance += $amount; |
| function transferFrom(&$sourceAccount,$amount){ |
| $sourceAccount->withdraw($amount); |
| 首先,我們建立一個(gè)測試類AccountTest,它是一個(gè)由PhpUnit提供的TestCase的子類。在這個(gè)TestCase類中有2個(gè)基本的方法:setUp和tearDown。 這2個(gè)方法的實(shí)現(xiàn)在父類中是空過程,必須由我們自己去重載。其中SetUp 用于進(jìn)行AccountTest類的初始化處理。在本例中,我們對(duì)一些在測試中用到的賬號(hào)進(jìn)行初始化。tearDown 則用于AccountTest類的清空處理,在本例中無需使用。因此,就不對(duì)它進(jìn)行重載。這樣AccountTester類的源代碼如下: |
| class AccountTester extends TestCase{ |
| function AccountTester($name){ |
| $this->TestCase($name); // call parent constructor |
| $this->_ac1 = new Account(100); // data for testWithdraw |
| $this->_ac2 = new Account(20); // data for testDeposit |
| $this->_ac3 = new Account(30); // data for testTransferFrom |
| $this->_ac4 = new Account(50); |
| 現(xiàn)在,我們可以往向AccountTester類加入測試代碼了。 |
| // Make a withdrawal of 25 units from _ac1. |
| // _ac1‘s initial balance is 100 |
| $this->_ac1->withdraw(25); |
| $this->assert($this->_ac1->getBalance() == 75); // 100 - 25 = 75 |
| // Make a deposit of 10 units into _ac2. |
| // _ac1‘s initial balance is 20 |
| $this->_ac2->deposit(10); |
| $this->assertEquals(30,$this->_ac2->getBalance()); //20 +10 = 30 |
| // Tranfers 10 units from _ac3 to _ac4 |
| // _ac3‘s initial balance is 30 |
| // _ac4‘s initial balance is 50 |
| function testTransferFrom(){ |
| $this->_ac4->transferFrom(&$this->_ac3,10); |
| $this->assertEquals(20,$this->_ac3->getBalance(),"Source account balance incorrect"); // 30 - 10 = 20 |
| $this->assertEquals(60,$this->_ac4->getBalance(),"Target account balance incorrect"); // 50 + 10 = 60 |
| 這段代碼中,assert(如同C里的斷言)方法是測試的關(guān)鍵部分。如果在assert中的條件表達(dá)式為真,那么測試通過。否則返回錯(cuò)誤。由于assert方法大都用于判斷兩個(gè)變量的值是否相等。因此,testclass類引入了assertEquals方法專門實(shí)現(xiàn)這個(gè)功能。AssertEquals方法中有3個(gè)參數(shù),依次分別為:期望值,測試值,兩值不相等時(shí)返回的消息提示串。 |
| 好了,現(xiàn)在可以運(yùn)行一下我們編好的測試程序了。我們還必須建立一個(gè)runtest.php測試程序來運(yùn)行所有的測試過程。 |
| $tSuite = new TestSuite(); //creation of the test suite object 創(chuàng)建測試套件對(duì)象 |
| $tSuite->addtest(new AccountTester("testWithdraw")); //Add inidividual tests |
| $tSuite->addtest(new AccountTester("testDeposit")); //加入專門測試方法。 |
| $tSuite->addtest(new AccountTester("testTransferFrom")); |
| $res = new TextTestResult(); //Creation of the Result 建立一個(gè)測試結(jié)果類 |
| $tSuite->run(&$res); //Run of the test 運(yùn)行測試 |
| $res->report(); //Print results 輸出測試結(jié)果。 |
| 首先創(chuàng)建測試套件對(duì)象tSuite,然后逐一加入專門測試方法,addtest方法的參數(shù)是測試方法的 再創(chuàng)建測試報(bào)告對(duì)象,隨之運(yùn)行測試。測試發(fā)現(xiàn)錯(cuò)誤的結(jié)果由TestResult類捕捉,TestResult可以定制一套text/html的錯(cuò)誤報(bào)告。如果有必要你也可以自己編寫輸出部分。測試結(jié)果封裝在TestResult類中,為了輸出測試結(jié)果。我們采用了phpUnit提供的另外一個(gè)類TextTestResult類,它可以輸出文本或超文本格式的報(bào)告。當(dāng)然我們也可以自己定制一個(gè)新的TestResult的子類控制更復(fù)雜的輸出格式。 |
| 1、在編寫一個(gè)新的測試套件完成之后,我們可以先引入一個(gè)小小的bug以證明測試套件可以正常運(yùn)行。 |
| 比如,在本例account類中,我們故意引入一個(gè)有問題的函數(shù)。 |
| function withdraw($amount){ |
| $this->balance -= $Amount; |
| // 變量名大小寫錯(cuò)誤,本意是調(diào)用$amount參數(shù),結(jié)果引入一個(gè)新變量$Amount。 |
| 好,現(xiàn)在讓我們運(yùn)行測試套件,如果不出意外的話,我們將很快發(fā)現(xiàn)錯(cuò)誤之處。 |
| 2.要指出的是,并非所有的方法都需要測試。你只需對(duì)相關(guān)的方法進(jìn)行測試。 |
| 3.如果在開始編碼前就寫好測試代碼,會(huì)使你更進(jìn)一步明白你的程序到底需要完成什么樣的任務(wù)。 |
| 現(xiàn)在,通過引入phpUnit的測試套件類,你可以發(fā)現(xiàn)找bug的時(shí)間縮短了,而你作為一個(gè)程序員的工作效率也提高了。 |
| 那么,盡情享受抓蟲子的樂趣吧。祝您好胃口。 :))) |
|