現(xiàn)在讓我們來創(chuàng)建一些測試的實例來詳細說明重構(gòu)后的運用程序應(yīng)該有的功能。
require_once ‘simpletest/unit_tester.php’; require_once ‘simpletest/reporter.php’; require_once ‘simpletest/mock_objects.php’; require_once ‘simpletest/web_tester.php’; require_once ‘classes.inc.php’; Session::init(); class PageWebTestCase extends WebTestCase { /*...*/ } class ResponseTestCase extends UnitTestCase { /*...*/ } class UserLoginTestCase extends UnitTestCase { /*...*/ } class SessionTestCase extends UnitTestCase { /*...*/ } class PageDirectorTestCase extends UnitTestCase { /*...*/ } $test = new GroupTest(‘Application PHP4 Unit Test’); $test->addTestCase(new PageWebTestCase); $test->addTestCase(new ResponseTestCase); $test->addTestCase(new UserLoginTestCase); $test->addTestCase(new SessionTestCase); $test->addTestCase(new PageDirectorTestCase);
這段代碼或多或少的展示了一個典型的運用程序的測試文件該是何種模樣。它一開始就包含了一些SimpleTest文件,也包括了用偽對象來測試的mock_object.php文件。接著,那些輔助類被包含進來,方法Session::init()被調(diào)用,seesion開始。
緊接著的全是以“安全無害”為目標而開始的測試實例,類WebTestCase確保所有程序按要求執(zhí)行, 然后是單獨的用于新設(shè)計的類的測試(盡管這種類本章不會詳述)。最后是我們接下去會討論的PageDirectorTestCase類。
類PageDirector的核心任務(wù)是協(xié)調(diào)類Session和類Response的對象,產(chǎn)生最終的網(wǎng)頁輸出結(jié)果。
Mock::Generate(‘Session’); Mock::Generate(‘Response’); define(‘SELF’, ‘testvalue’); class PageDirectorTestCase extends UnitTestCase { // ... }
在這段代碼的一開始,Mock::generate()創(chuàng)建了偽對象類的定義并定義了一個后面將要用到的常量。
假設(shè)對類Session 和類 Response的測試已經(jīng)存在,下一步就是創(chuàng)建偽Session來模擬類 Session的狀態(tài)。這個偽對象的設(shè)置和我們一開始所演示的例子極其類似。
因為PageDirector::run()方法正回顯內(nèi)容,你可以用輸出緩存內(nèi)容的辦法來捕獲它,看看是否正確。
class PageDirectorTestCase extends UnitTestCase { // ... function TestLoggedOutContent() { $session =& new MockSession($this); $session->setReturnValue(‘get’, null, array(‘user_name’)); $session->expectOnce(‘get’, array(‘user_name’)); $page =& new PageDirector($session, new Response); ob_start(); $page->run(); $result = ob_get_clean(); $this->assertNoUnwantedPattern(‘/secret.*content/i’, $result); $this->assertWantedPattern(‘/<form.*<input[^>]*text[^>]*’ .’name.*<input[^>]*password[^>]*passwd/ims’ ,$result); $session->tally(); } }
這段代碼證明了在SimpleTest中使用偽對象的必要性。我們來看看其中創(chuàng)建偽對象的一行代碼$session =&new MockSession($this)。你可以使用繼承自SimpleStub類(參見http://simpletest.sf.net/SimpleTest/MockObjects/SimpleStub.html#sec-methodsummary)的方法來創(chuàng)建你所希望的從對象(如同你在測試代碼時所做的那樣)返回的結(jié)果.下一步,實例化PageDirector類并用MockSession代替正式使用時的類來實例化相關(guān)代碼。
注:setReturnValue()方法 setReturnValue()方法通過指定當(dāng)偽對象的特定方法被調(diào)用時返回何值來讓偽對象以一個“替身”的身份融入代碼。已經(jīng)有了一些這種方法的變體:比如指定以一定次序返回一系列值的做法,還有以參數(shù)代替值來返回結(jié)果的做法。 expectOnce()方法 expectOnce()方法通過建立一些假想,這些假想是關(guān)于什么時候方法被調(diào)用以及多久調(diào)用一次,來允許你的偽對象以“批評者”的角色來測試代碼。這些假想當(dāng)你在測試中調(diào)用偽對象的tally()方法時會被報告。
class PageDirector { var $session; var $response; function PageDirector(&$session, &$response) { $this->session =& $session; $this->response =& $response; } }
因為PageDirector類認為自己不是處于一個測試環(huán)境而是處于一個真實正常的運用程序環(huán)境中,它回顯結(jié)果到瀏覽器。既然你實際上在測試時并不希望這個動作,你就可以通過PHP輸出緩存的特性(參見http://php.net/outcontrol)來捕獲執(zhí)行時它往瀏覽器發(fā)送了什么。
class PageDirector { // ... function run() { if (!$this->isLoggedIn()) { $this->showLogin(); } $this->response->display(); } function isLoggedIn() { return ($this->session->get(‘user_name’)) ? true : false; } function showLogin() { $this->response->addBody(‘<form method=”post”>’); $this->response->addBody(‘Name:<input type=”text” name=”name”>’); $this->response->addBody(“\n”); $this->response->addBody( ‘Password:<input type=”password” name=”passwd”>’); $this->response->addBody(“\n”); $this->response->addBody(‘<input type=”submit” value=”Login”>’); $this->response->addBody(‘</form>’); } }
如同這段程序代碼一樣,測試代碼本身也可以進行重構(gòu)。在本例中,你可以看到緩存輸出的訣竅是其將被多次復(fù)用,因此使用“析構(gòu)法”重構(gòu)可以使測試本身簡化。(重新調(diào)用的那些以“test”為開頭的方法是隨整個測試一起自動運行的;你也可以自己創(chuàng)建一些使測試更簡潔的方法。)
出處:phpchina
責(zé)任編輯:bluehearts
上一頁 php設(shè)計模式介紹之偽對象模式 [4] 下一頁 php設(shè)計模式介紹之偽對象模式 [6]
◎進入論壇網(wǎng)絡(luò)編程版塊參加討論
|