W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
CodeIgniter的構(gòu)建旨在使對框架和應(yīng)用程序的測試盡可能簡單。PHPUnit
內(nèi)置對它的支持,并且該框架提供了許多方便的輔助方法,以使您的應(yīng)用程序的各個方面的測試盡可能輕松。
CodeIgniter使用phpUnit作為所有測試的基礎(chǔ)。有兩種方法可以安裝phpUnit以在系統(tǒng)中使用。
推薦的方法是使用Composer將其安裝在項目中。盡管可以在全球范圍內(nèi)安裝它,但我們不建議您這樣做,因為隨著時間的流逝,它可能會導(dǎo)致與系統(tǒng)上其他項目的兼容性問題。
確保系統(tǒng)上已安裝Composer。在項目根目錄(包含應(yīng)用程序和系統(tǒng)目錄的目錄)中,從命令行鍵入以下內(nèi)容:
> composer require --dev phpunit/phpunit
這將為您當(dāng)前的PHP版本安裝正確的版本。完成后,您可以通過鍵入以下內(nèi)容運行該項目的所有測試:
> ./vendor/bin/phpunit
另一個選擇是從phpUnit網(wǎng)站下載.phar文件。這是一個獨立文件,應(yīng)放置在項目根目錄下。
框架phpunit.xml.dist
在項目根目錄中有一個文件。這控制了框架本身的單元測試。如果您提供自己的phpunit.xml
,它將超越此。
您phpunit.xml
應(yīng)該排除的system
文件夾,以及任何vendor
或 ThirdParty
文件夾,如果你是單元測試您的應(yīng)用程序。
為了利用所提供的其他工具,您的測試必須擴展CIUnitTestCase
。默認(rèn)情況下,所有測試均應(yīng)位于tests / app目錄中。
要測試新庫Foo,您可以在tests / app / Libraries / FooTest.php中創(chuàng)建一個新文件:
<?php namespace App\Libraries;
use CodeIgniter\Test\CIUnitTestCase;
class FooTest extends CIUnitTestCase
{
public function testFooNotBar()
{
. . .
}
}
要測試您的模型之一,您可能會在以下代碼中得到以下結(jié)果tests/app/Models/OneOfMyModelsTest.php
:
<?php namespace App\Models;
use CodeIgniter\Test\CIUnitTestCase;
class OneOfMyModelsTest extends CIUnitTestCase
{
public function testFooNotBar()
{
. . .
}
}
您可以創(chuàng)建適合您的測試樣式/需求的任何目錄結(jié)構(gòu)。為測試類命名時,請記住app目錄是App
名稱空間的根,因此您使用的任何類都必須具有相對于的正確名稱空間App
。
注解
測試類并非嚴(yán)格要求使用名稱空間,但是它們有助于確保沒有類名沖突。
測試數(shù)據(jù)庫結(jié)果時,必須使用CIDatabaseTestClass類。
CIUnitTestCase
提供了其他可能有用的單元測試斷言。
assertLogged($ level,$ expectedMessage)
確保您希望實際記錄的內(nèi)容是:
$config = new LoggerConfig();
$logger = new Logger($config);
... do something that you expect a log entry from
$logger->log('error', "That's no moon");
$this->assertLogged('error', "That's no moon");
assertEventTriggered($ eventName)
確保您希望觸發(fā)的事件實際上是:
Events::on('foo', function($arg) use(&$result) {
$result = $arg;
});
Events::trigger('foo', 'bar');
$this->assertEventTriggered('foo');
assertHeaderEmitted($ header,$ ignoreCase = false)
確保實際上發(fā)出了標(biāo)頭或cookie:
$response->setCookie('foo', 'bar');
ob_start();
$this->response->send();
$output = ob_get_clean(); // in case you want to check the actual body
$this->assertHeaderEmitted("Set-Cookie: foo=bar");
注意:與此相關(guān)的測試案例應(yīng)在PHPunit中作為單獨的進程運行。
assertHeaderNotEmitted($ header,$ ignoreCase = false)
確保沒有發(fā)出標(biāo)題或cookie:
$response->setCookie('foo', 'bar');
ob_start();
$this->response->send();
$output = ob_get_clean(); // in case you want to check the actual body
$this->assertHeaderNotEmitted("Set-Cookie: banana");
注意:與此相關(guān)的測試案例應(yīng)在PHPunit中作為單獨的進程運行。
assertCloseEnough($ expected,$ actual,$ message ='',$ tolerance = 1)
對于延長的執(zhí)行時間測試,請測試預(yù)期時間與實際時間之間的絕對差是否在規(guī)定的公差內(nèi):
$timer = new Timer();
$timer->start('longjohn', strtotime('-11 minutes'));
$this->assertCloseEnough(11 * 60, $timer->getElapsedTime('longjohn'));
上述測試將允許實際時間為660或661秒。
assertCloseEnoughString($ expected,$ actual,$ message ='',$ tolerance = 1)
對于延長的執(zhí)行時間測試,測試預(yù)期時間與實際時間之間的絕對差(格式為字符串)是否在規(guī)定的公差范圍內(nèi):
$timer = new Timer();
$timer->start('longjohn', strtotime('-11 minutes'));
$this->assertCloseEnoughString(11 * 60, $timer->getElapsedTime('longjohn'));
上述測試將允許實際時間為660或661秒。
測試時,可以使用以下setter和getter方法訪問要測試的類中的受保護的方法和私有方法以及屬性。
getPrivateMethodInvoker($ instance,$ method)
使您可以從類外部調(diào)用私有方法。這將返回一個可以調(diào)用的函數(shù)。第一個參數(shù)是要測試的類的實例。第二個參數(shù)是您要調(diào)用的方法的名稱。
// Create an instance of the class to test
$obj = new Foo();
// Get the invoker for the 'privateMethod' method.
$method = $this->getPrivateMethodInvoker($obj, 'privateMethod');
// Test the results
$this->assertEquals('bar', $method('param1', 'param2'));
getPrivateProperty($ instance,$ property)
從類的實例中檢索私有/受保護的類屬性的值。第一個參數(shù)是要測試的類的實例。第二個參數(shù)是屬性的名稱。
// Create an instance of the class to test
$obj = new Foo();
// Test the value
$this->assertEquals('bar', $this->getPrivateProperty($obj, 'baz'));
setPrivateProperty($ instance,$ property,$ value)
在類實例中設(shè)置一個受保護的值。第一個參數(shù)是要測試的類的實例。第二個參數(shù)是要為其設(shè)置值的屬性的名稱。第三個參數(shù)是將其設(shè)置為的值:
// Create an instance of the class to test
$obj = new Foo();
// Set the value
$this->setPrivateProperty($obj, 'baz', 'oops!');
// Do normal testing...
您通常會發(fā)現(xiàn)您需要模擬app / Config / Services.php中定義的服務(wù)之一,以將測試限制為僅涉及代碼,同時模擬服務(wù)的各種響應(yīng)。在測試控制器和其他集成測試時尤其如此。該服務(wù)類提供了兩個方法,使這個簡單的:injectMock()
和reset()
。
injectMock()
此方法允許您定義Services類將返回的確切實例。您可以使用它來設(shè)置服務(wù)的屬性,使其以某種方式運行,或者將服務(wù)替換為模擬類。
public function testSomething()
{
$curlrequest = $this->getMockBuilder('CodeIgniter\HTTP\CURLRequest')
->setMethods(['request'])
->getMock();
Services::injectMock('curlrequest', $curlrequest);
// Do normal testing here....
}
第一個參數(shù)是您要替換的服務(wù)。該名稱必須與Services類中的函數(shù)名稱完全匹配。第二個參數(shù)是要替換為的實例。
reset()
從Services類中刪除所有模擬的類,使其恢復(fù)到原始狀態(tài)。
CITestStreamFilter提供了這些輔助方法的替代方法。
您可能需要測試難以測試的事物。有時,捕獲流(例如PHP自己的STDOUT或STDERR)可能會有所幫助。將CITestStreamFilter
幫助您從您所選擇的流捕獲輸出。
在您的一個測試用例中演示此示例:
public function setUp()
{
CITestStreamFilter::$buffer = '';
$this->stream_filter = stream_filter_append(STDOUT, 'CITestStreamFilter');
}
public function tearDown()
{
stream_filter_remove($this->stream_filter);
}
public function testSomeOutput()
{
CLI::write('first.');
$expected = "first.\n";
$this->assertEquals($expected, CITestStreamFilter::$buffer);
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: