舉例詳解PHP腳本的測試方法
一、常用測試示例
我們經(jīng)常會(huì)遇到這種情況:將一些沒有經(jīng)過任何測試的遺留代碼進(jìn)行重新編寫測試,甚至這些代碼還是用面向?qū)ο髮懙?。要?duì)這樣的代碼進(jìn)行測試,我的建議是把代碼分解成塊,這樣就容易測試了。
然而,這些遺留代碼并不是那么好重構(gòu)的,比如:測試前,你不能在把代碼重新編寫,這是為了避免影響原有程序,當(dāng)然也不好進(jìn)行單元測試。
在PHP程序中,通常有一部分代碼是寫在幾個(gè)index.php和script.php文件中的,這些.php文件存放在幾個(gè)不同的文件夾里。如果不找到它們的入口點(diǎn),是無法直接由Web服務(wù)器訪問的。
測試副本
要測試一個(gè)PHP腳本,我們需要模擬一個(gè)HTTP請(qǐng)求,并檢查返回的響應(yīng)(response)是否等于預(yù)期值。這里需要注意的是模擬一個(gè)請(qǐng)求,要定義response和request,這不僅僅是內(nèi)容(content)的不同,而且他們的頭信息(header)也是不同的。
此外,如果我們想要測試一個(gè)操作數(shù)據(jù)的事務(wù)腳本,我們要確保不讓它去連接真正的數(shù)據(jù)庫或應(yīng)用程序的其余部分。
在現(xiàn)實(shí)中,通常沒有人會(huì)直接拿原有的PHP腳本進(jìn)行重寫測試。因?yàn)榕掳汛a弄得不可恢復(fù)。我建議使用PHP腳本的副本,這樣我們就可以將PHP代碼進(jìn)行一些小手術(shù)了。
如何將代碼進(jìn)行最小修改:刪除include和require語句(如果它們沒有被用到),并且修改內(nèi)部函數(shù)的調(diào)用方式,例如:將header()寫成$object->header()。
最后,我們來測試這個(gè)事務(wù)腳本。測試完后,我們可以從副本腳本中提取出它們,并把它們放入新腳本文件中。
具體步驟
一、模擬一個(gè)HTTP請(qǐng)求并重新定義變量$_GET和$_POST,還要修改$_SERVER的header。
二、獲取請(qǐng)求響應(yīng),response的body可以通過ob_start()和ob_get_clean()捕獲,它可以收集每一個(gè)用echo()或以<?php標(biāo)簽輸出的buffer(緩沖內(nèi)容)。
注意:輸出緩沖支持在PHP多個(gè)級(jí)別的嵌套,所以在大多數(shù)情況下,都可以捕獲到,即使腳本在使用ob_*調(diào)用本身。
三、測試腳本應(yīng)包含事務(wù)腳本的內(nèi)部方法,因此在這個(gè)腳本范圍內(nèi)的方法都可以被調(diào)用。例如:
1.腳本所需的變量可以被定義為局部變量封裝起來,如$connection作為一個(gè)數(shù)據(jù)庫連接。
2.不是原本PHP的內(nèi)置函數(shù),應(yīng)該加上對(duì)象來調(diào)用,如:header()寫成$this->header()。
具體代碼
這就是我們要測試的事務(wù)腳本對(duì)象,具體到腳本中,我們還需要封裝:
<?php
class ForumPosting
{
private $headers = array();
public function handleRequest($postRequest)
{
$_POST = $postRequest;
$connection = $this->getAConnection();
ob_start();
include 'forum/post_new_copy.php';
$content = ob_get_clean();
return array(
'content' => $content,
'headers' => $this->headers
);
}
private function header($headerLine)
{
$this->headers[] = $headerLine;
}
...
}
這是我們的測試代碼:
public function testANewPostIsCreated()
{
$action = new ForumPosting();
$response = $action->handleRequest(array(
'id_thread' => 42,
'text' => 'Hello, world',
...
));
$this->assertEquals('...', $response['content']);
$this->assertContains('Content-type: text/html', $response['headers']);
}
測試副本只是暫時(shí)的!它讓我們編寫的測試不會(huì)改變。最終,我們要將已經(jīng)通過測試的PHP腳本進(jìn)行重構(gòu),以消除冗余代碼。
當(dāng)我們的測試完成后,可以將handleRequest()的內(nèi)容替換成真正的邏輯代碼。假如你要寫很多這樣的測試腳本,你可以寫一個(gè)通用的測試對(duì)象,以滿足你的測試需要。
二、PHP開發(fā)者的單元測試工具包
在PHP領(lǐng)域,單元測試的工具主要有PHPUNIT,PHPUNIT2和SimpleTest三種。其中PHPUNIT在功能上很簡單,不算完善;PHPUNIT2是專門為PHP5寫的單元測試工具,在結(jié)構(gòu)和功能上都向Junit看齊;而SimpleTest則是一套非常實(shí)用的測試工具,其中的webTest支持對(duì)web程序界面的測試,是Easy最為推薦的一款測試工具。在本文中,我們選擇SimpleTest進(jìn)行介紹。
相關(guān)知識(shí):PHPUNIT2也是一款很好的工具,尤其是架構(gòu)上有很多值得圈點(diǎn)之處,希望將來能有機(jī)會(huì)在專門的文章中和大家分享。
SimpleTest:就是這么Simple
安裝SimpleTest很簡單,上sf.net上下載一個(gè)源碼包,然后解壓到web目錄下就可以使用了,這里就不多說。
下面我們先來看個(gè)例子:編寫一個(gè)測試,檢查一個(gè)網(wǎng)站是否可以訪問。
首先我們引入要用到的文件:
代碼列表:
require_once("../simpletest/unit_tester.php");
require_once("../simpletest/web_tester.php");
require_once("../simpletest/reporter.php");
然后我們創(chuàng)建一個(gè)測試類:
代碼列表:
class TestOfSite extends WebTestCase
{
function TestOfSite()
{
$this->WebTestCase("測試");
}
function testSite()
{
$this->get("http://howgo.net/prettyface/display.php");
$this->assertTitle(".: facebook :.");
}
}
首先我們擴(kuò)展了webTestCase類,這樣我們就可以自動(dòng)獲得測試web的能力,然后在構(gòu)造函數(shù)中我們直接使用基類的,只是把標(biāo)題傳給它。接著我們就該寫測試方法了,測試方法都是以‘test"開頭的,用以識(shí)別在我們運(yùn)行測試的時(shí)候,類中哪些方法要進(jìn)行調(diào)用。
而$this->get將取得網(wǎng)頁的內(nèi)容,我們指定它的標(biāo)題為 ".: facebook :.", 接著我們要做的就是實(shí)例化這個(gè)類的對(duì)象,并運(yùn)行它。
代碼列表:
$test = &new TestOfSite(); $test->run(new HtmlReporter());
下邊是運(yùn)行結(jié)果:
如果測試出錯(cuò)則會(huì)出現(xiàn)下邊的界面:
到這里一個(gè)簡單的測試就算完成了。
實(shí)戰(zhàn)演習(xí) – 一個(gè)Login測試
下面我們進(jìn)入實(shí)戰(zhàn),在這個(gè)基礎(chǔ)上完成一個(gè)login的測試。這次我們先貼出完整的代碼:
代碼列表:
require_once("../simpletest/unit_tester.php");
require_once("../simpletest/web_tester.php");
require_once("../simpletest/reporter.php");
class TestOfLogin extends WebTestCase
{
function TestOfLogin()
{
$this->WebTestCase("Login測試");
}
function testLoginOk()
{
// 取得頁面
$this->get("http://howgo.net/prettyface/login.php");
// 添加測試表項(xiàng)
$this->setField("name","Easy");
$this->setField("pass","******");
// 提交
$this->clickSubmit("提交");
// 察看提交后返回頁面是否正確
$this->assertWantedPattern("/成功登錄/");
// 點(diǎn)擊頁面鏈接
$this->clickLink("點(diǎn)擊這里進(jìn)入管理頁面");
// 察看指定頁面標(biāo)題和關(guān)鍵內(nèi)容
$this->assertTitle("ADMINCP");
$this->assertWantedPattern("/請(qǐng)選擇要進(jìn)行的任務(wù)/");
// 退出登陸
$this->clickLink("退出管理");
$this->clickLink
}
}
相關(guān)文章
php實(shí)現(xiàn)的后臺(tái)表格分頁功能示例
這篇文章主要介紹了php實(shí)現(xiàn)的后臺(tái)表格分頁功能,涉及php針對(duì)數(shù)據(jù)庫的連接、查詢、刪除、動(dòng)態(tài)生成表格等相關(guān)操作技巧,需要的朋友可以參考下2017-10-10
ThinkPHP3.2.3所有的單字母方法整理總結(jié)
ThinkPHP3.2.3在以前是一款廣受歡迎的PHP開發(fā)框架,現(xiàn)在雖然除了版本5和6,但仍有不少項(xiàng)目使用ThinkPHP3。ThinkPHP3中的字母函數(shù)是以字母開頭的一類函數(shù),其作用是非常豐富的,包括字符串處理、文件處理、日期時(shí)間處理以及HTTP協(xié)議處理等。2023-07-07
淺析application/x-www-form-urlencoded和multipart/form-data的區(qū)別
我們知道在通過POST方式向服務(wù)器發(fā)送AJAX請(qǐng)求時(shí)最好要通過設(shè)置請(qǐng)求頭來指定為application/x-www-form-urlencoded編碼類型。知道通過表單上傳文件時(shí)必須指定編碼類型為"multipart/form-data"。那么為什么要這么設(shè)置呢2014-06-06
php實(shí)現(xiàn)構(gòu)建排除當(dāng)前元素的乘積數(shù)組方法
在本篇文章中我們給大家整理了關(guān)于php實(shí)現(xiàn)構(gòu)建排除當(dāng)前元素的乘積數(shù)組的方法以及相關(guān)實(shí)例代碼,有需要的朋友們參考下。2018-10-10

