具備高效的測(cè)試一如編寫(xiě)高效的應(yīng)用一樣重要图甜。作為開(kāi)發(fā)者來(lái)說(shuō),迅速得知你剛編寫(xiě)的代碼是否能夠正常運(yùn)行,能夠讓開(kāi)發(fā)效率大大提升规阀。接下來(lái)我們將會(huì)介紹一些可以快速實(shí)現(xiàn)的小技巧,讓你的代碼測(cè)試變得更快瘦麸。
該示例測(cè)試套件有意地模擬更廣泛的測(cè)試集合谁撼,并突出改進(jìn)的可行性。真實(shí)情況下,效率的提升可能有所差異厉碟。
ParaTest
這個(gè)包 是一個(gè)用來(lái)運(yùn)行你的測(cè)試套件的 PHPUnit
擴(kuò)展喊巍。 和 PHPUnit
不一樣的是它可以利用你的多核 CPU
來(lái)并行的運(yùn)行測(cè)試用例。
你可以通過(guò) composer
來(lái)將它作為一個(gè)開(kāi)發(fā)依賴(lài)安裝以后開(kāi)始使用 ParaTest
箍鼓。
composer require --dev brianium/paratest
現(xiàn)在我們就可以像調(diào)用 PHPUnit
一樣來(lái)調(diào)用 ParaTest
了崭参。它會(huì)自動(dòng)的根據(jù)你機(jī)器 CPU
核心數(shù)來(lái)判斷要啟動(dòng)多少個(gè)進(jìn)程。
<img src="https://user-gold-cdn.xitu.io/2019/1/21/1686e1efd40e5bd7?w=1440&h=611&f=png&s=233798" class="rm-style">
上面款咖,你可以看到在控制臺(tái)中輸出了運(yùn)行測(cè)試用例啟動(dòng)了5個(gè)并行的進(jìn)程何暮。對(duì)比一下,下面用 PHPUnit 運(yùn)行了同樣的測(cè)試用例铐殃。
<img src="https://user-gold-cdn.xitu.io/2019/1/21/1686e1efd2d2a874?w=525&h=177&f=png&s=20131" class="rm-style">
1.49 秒 和 6.15秒 !
盡管 ParaTest 可以自己確定進(jìn)程數(shù)海洼,你也可以嘗試設(shè)置進(jìn)程數(shù)針對(duì)你的機(jī)器進(jìn)行優(yōu)化。使用 ---processes
選項(xiàng)富腊,你可以增加或減少進(jìn)程數(shù)坏逢,因?yàn)椴⒉皇沁M(jìn)程數(shù)越多測(cè)試效果越好。
./vendor/bin/paratest --processes 6
警告: 使用 ParaTest 測(cè)試數(shù)據(jù)庫(kù)前赘被,需要考慮如何準(zhǔn)備數(shù)據(jù)是整。如果使用 Lavarel 的 RefreshDatabase
,運(yùn)行測(cè)試用例后會(huì)回滾或者遷移數(shù)據(jù)庫(kù)來(lái)寫(xiě)入 民假。 相反的是浮入,通過(guò) DatabaseTransactions
跳過(guò)數(shù)據(jù)持久化, 這在運(yùn)行測(cè)試期間不會(huì)嘗試修改數(shù)據(jù)羊异。
重試失敗的測(cè)試
PHPUnit 有個(gè)非常方便的功能就是舵盈,允許你重新只運(yùn)行上次測(cè)試中失敗的測(cè)試.。如果你正在進(jìn)行紅綠復(fù)建風(fēng)格的 TDD 開(kāi)發(fā)球化,它將會(huì)加快你的開(kāi)發(fā)周期秽晚。讓我們從一個(gè)通過(guò)所有現(xiàn)存測(cè)試的測(cè)試套件來(lái)了解一下它這個(gè)功能。
<img src="https://user-gold-cdn.xitu.io/2019/1/21/1686e1efface2e99?w=525&h=162&f=png&s=13166" class="rm-style">
接下來(lái)筒愚,新增一個(gè) red-green-refactor 測(cè)試模型的測(cè)試用例赴蝇,預(yù)期失敗:
<img src="https://user-gold-cdn.xitu.io/2019/1/21/1686e1effad4dc01?w=525&h=151&f=png&s=12965" class="rm-style">
在更改代碼庫(kù)之后你認(rèn)為新測(cè)試會(huì)通過(guò)巢掺,你想重新運(yùn)行該測(cè)試套件以期能按預(yù)期運(yùn)行句伶。問(wèn)題在于這個(gè)套件現(xiàn)在已經(jīng)要花 1.3 秒的時(shí)間才能運(yùn)行,隨著測(cè)試代碼量的增加陆淀,所需嚴(yán)重等待的時(shí)間也隨之增加考余。
如果我們只能運(yùn)行失敗的測(cè)試,那不是很好轧苫? 非常幸運(yùn)的是 PHPUnit v7.3添加了這樣做的能力楚堤。
<img src="https://user-gold-cdn.xitu.io/2019/1/21/1686e1effaec15cb?w=525&h=151&f=png&s=11977" class="rm-style">
為了實(shí)現(xiàn)這個(gè)功能,請(qǐng)將 cacheResult =“true”
添加到 phpunit.xml
配置中。 PHPUnit 會(huì)始終記住以前哪些測(cè)試失敗了身冬。
<?xml version="1.0" encoding="UTF-8"?>
<phpunit cacheResult="true"
backupGlobals="false"
...>
現(xiàn)在衅胀,當(dāng)我們運(yùn)行我們的測(cè)試單元時(shí), PHPUnit 將記住哪些測(cè)試失敗并使用以下選項(xiàng)讓我們可以重新運(yùn)行那些失敗的測(cè)試單元酥筝。
./vendor/bin/phpunit --order-by=defects --stop-on-defect
我們不再需要等待整個(gè)測(cè)試單元運(yùn)行滚躯,以查看我們?cè)噲D解決的一個(gè)測(cè)試是否正在通過(guò)。
將緩存文件 .phpunit.result.cache
添加到 .gitignore
也是一個(gè)好主意嘿歌,這樣它就不會(huì)最終被提交到你的倉(cāng)庫(kù)里掸掏。
慢測(cè)試分組
PHPUnit 允許你用 @group
注解來(lái)將測(cè)試用例添加到不同的「分組」。如果你有一些測(cè)試用例尤其的慢的話(huà)宙帝,最好是將他們分到同一個(gè)組丧凤。
class MyTest extends TestCase
{
public function test_that_is_fast()
{
$this->assertTrue(true);
}
/**
* @group slow
*/
public function test_that_is_slow()
{
sleep(10);
$this->assertTrue(true);
}
/**
* @group slow
*/
public function test_that_is_slow_2_adrians_revenge()
{
sleep(10);
$this->assertFalse(false);
}
}
在這個(gè)例子中,我們有兩個(gè)測(cè)試用例要運(yùn)行10秒鐘茄唐。 在我們開(kāi)發(fā)周期內(nèi)最后一件要做的事情就是運(yùn)行測(cè)試用例,尤其是在做測(cè)試驅(qū)動(dòng)開(kāi)發(fā)的時(shí)候需要測(cè)試用例瞬時(shí)執(zhí)行完成蝇更。
由于兩個(gè)慢的測(cè)試用例都在同一個(gè)分組所以你可以通過(guò) PHPUnit 的 --exclude-group
選項(xiàng)在某一次測(cè)試運(yùn)行中來(lái)排除他們沪编。
./vendor/bin/phpunit --exclude-group slow
這個(gè)命令將會(huì)運(yùn)行你測(cè)試用例中除了 slow
分組的所有測(cè)試用例。 測(cè)試用例分組還有一個(gè)好處年扩,比如說(shuō)你需要將你所有的慢測(cè)試用例整理成文檔以便后面再來(lái)優(yōu)化他們蚁廓。
然而在部署到生產(chǎn)環(huán)境前進(jìn)行一些檢查確保所有測(cè)試用例能通過(guò),包括慢的測(cè)試用例厨幻。 設(shè)置一個(gè) CI
管道來(lái)運(yùn)行測(cè)試用例會(huì)是個(gè)不錯(cuò)的方法相嵌。
過(guò)濾測(cè)試
PHPUnit 有一個(gè) --filter
選項(xiàng),它接受一個(gè)模式來(lái)確定運(yùn)行哪些測(cè)試况脆。例如饭宾,如果您將所有測(cè)試配置命名空間 ,則可以通過(guò)指定命名空間來(lái)運(yùn)行特定的測(cè)試子集格了。 以下命令僅在 Tests\Unit\Models
命名空間中運(yùn)行測(cè)試并排除所有其他命令看铆。
./vendor/bin/phpunit --filter 'Tests\\Unit\\Models'
--filter
選項(xiàng)是靈活的,允許通過(guò) methodName
盛末,Class::methodName
進(jìn)行過(guò)濾弹惦,甚至可以通過(guò)帶有 /path/to/my/test.php
的文件路徑進(jìn)行過(guò)濾。您應(yīng)該查看此選項(xiàng)的 PHPUnit docs 并查看更多的內(nèi)容悄但。
密碼哈希次數(shù)
Laravel 默認(rèn)使用 bcrypt 密碼哈希算法棠隐,這種設(shè)計(jì)在系統(tǒng)資源上緩慢且昂貴。如果您的測(cè)試是驗(yàn)證用戶(hù)密碼檐嚣,可以通過(guò)設(shè)置算法使用的次數(shù)來(lái)減少測(cè)試運(yùn)行的時(shí)間助泽,因?yàn)樗鼒?zhí)行的次數(shù)越多,所需的時(shí)間就越長(zhǎng)。
如果你的應(yīng)用程序與 laravel/laravel
project 中的最新更改保持同步报咳,你會(huì)發(fā)現(xiàn)哈希次數(shù)的數(shù)量可以使用環(huán)境變量進(jìn)行自定義侠讯。bcrypt 允許的最小次數(shù)已經(jīng)設(shè)置為4,在 phpunit.xml
file.
但是暑刃,如果您沒(méi)有同步最新的更新厢漩,可以使用 Hash
門(mén)面在CreatesApplication
trait 中設(shè)置它。
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
// 設(shè)置 bcrypt 哈希次數(shù)...
Hash::rounds(4);
return $app;
}
內(nèi)存數(shù)據(jù)庫(kù)
利用內(nèi)存數(shù)據(jù)庫(kù) SQLite 岩臣,是另一種加速測(cè)試的方式溜嗜。 你可以通過(guò)在 phpunit.xml
配置文件里添加兩個(gè)環(huán)境字段,來(lái)迅速開(kāi)啟它架谎。
<php>
...
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
</php>
說(shuō)明:盡管這樣看上去很容易炸宵,你應(yīng)該考慮生產(chǎn)環(huán)境數(shù)據(jù)庫(kù)一致性問(wèn)題。如果你在生產(chǎn)環(huán)境使用了 MySQL 數(shù)據(jù)庫(kù)谷扣,你應(yīng)該警惕引入不同數(shù)據(jù)庫(kù)所帶來(lái)的測(cè)試上的不同土全,比如 SQLite。我在這篇文章 my feature test suite setup 里描述了很多細(xì)節(jié)上的不同點(diǎn)会涎。我認(rèn)為相比通過(guò)提升一點(diǎn)速度帶來(lái)的好處裹匙,保持生產(chǎn)環(huán)境一致更重要。
禁用 Xdebug
如果你平時(shí)用不到 Xdebug 的話(huà)末秃,可以禁用掉它概页,因?yàn)樗鼤?huì)降低 PHP 執(zhí)行速度,導(dǎo)致測(cè)試用例運(yùn)行緩慢练慕。如果你日常使用它來(lái)調(diào)試的話(huà)惰匙,為了執(zhí)行測(cè)試而禁用它可能不是一個(gè)好的選擇 —— 但你始終要知道這一點(diǎn)當(dāng)你關(guān)注測(cè)試用例執(zhí)行速度時(shí)。
你可以在下面這個(gè)測(cè)試用例看到铃将,一旦我們禁用了 Xdebug项鬼,執(zhí)行速度將會(huì)有極大的提高。下面是這個(gè)測(cè)試用例在 Xdebug 啟用時(shí)的執(zhí)行情況:
<img src="https://user-gold-cdn.xitu.io/2019/1/21/1686e1f022f017f1?w=525&h=151&f=png&s=11703" class="rm-style">
以及同樣的測(cè)試用例在 Xdebug 禁用時(shí)的執(zhí)行情況:
<img src="https://user-gold-cdn.xitu.io/2019/1/21/1686e1f023050434?w=525&h=151&f=png&s=11374" class="rm-style">
修復(fù)測(cè)試速度過(guò)慢
當(dāng)然我們最希望看到的段落是是:修復(fù)測(cè)試速度過(guò)慢劲阎!如果您正在努力確定哪些測(cè)試導(dǎo)致測(cè)試單元變慢時(shí)秃臣,您可能需要查看 PHPUnit Report 。它是一個(gè)開(kāi)源工具哪工,允許您通過(guò)生成如下所示的云可視化您的測(cè)試單元的性能奥此,其中較大的氣泡代表慢速測(cè)試。這將使您能夠在單元中找到最慢的測(cè)試并逐步提高其性能雁比。
轉(zhuǎn)自 PHP / Laravel 開(kāi)發(fā)者社區(qū) https://laravel-china.org/topics/22341