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