就一般的開(kāi)發(fā)程序員而言,code過(guò)程中調(diào)試奈懒、測(cè)試都是必不可少的奠涌。受影響于從事C++開(kāi)發(fā)時(shí)養(yǎng)成的習(xí)慣,調(diào)試呢有斷點(diǎn)調(diào)試磷杏,開(kāi)發(fā)測(cè)試呢有單元測(cè)試溜畅。然餓,作為一種Web開(kāi)發(fā)腳本語(yǔ)言极祸,PHP斷點(diǎn)調(diào)試[看不到變量及堆棧信息]:一堆的var_dump,echo??或者稍有點(diǎn)技術(shù)含量的log_message?更甚至借助第三方工具Xdebug慈格?。遥金。浴捆。。稿械。這點(diǎn)我們暫不考慮选泻,此處討論的重點(diǎn)主要圍繞“單元測(cè)試”。
無(wú)論是測(cè)試即有代碼還是為編寫新的代碼美莫,亦或是為重構(gòu)老的代碼做準(zhǔn)備页眯,單元測(cè)試的作用歸根結(jié)底就是保護(hù)。正確的單元測(cè)試就是確保測(cè)試代碼準(zhǔn)確隔離(isolate)了測(cè)試代碼茂嗓,常見(jiàn)的有TDD餐茵,BDD,DDD(領(lǐng)域驅(qū)動(dòng)開(kāi)發(fā))述吸。
TDD忿族,即測(cè)試驅(qū)動(dòng)開(kāi)發(fā),是一種利用測(cè)試受益的方法論(或者說(shuō)實(shí)踐準(zhǔn)則)蝌矛。簡(jiǎn)單地說(shuō)道批,TDD 就是在寫代碼前先寫測(cè)試,并嚴(yán)格遵循red => green => refactor(錯(cuò)誤 => 正確 => 重構(gòu))的流程入撒,所以才叫做“測(cè)試驅(qū)動(dòng)開(kāi)發(fā)”隆豹。一般大致兩種情形是適合的:1.準(zhǔn)備編寫自己覺(jué)得“沒(méi)譜”的代碼;2.準(zhǔn)備重構(gòu)即有代碼茅逮,有可能是改善璃赡,也有可能是添加新的功能特性或處理新條件的邏輯判哥,再有就是修復(fù) Bug 等,在這里我都籠統(tǒng)的歸為重構(gòu)碉考。
?Bug 通常都是用戶在使用過(guò)程中反饋來(lái)的(我把測(cè)試人員也算在用戶之中)塌计,用戶接觸不到更深更內(nèi)在的結(jié)構(gòu),他們都是通過(guò)用戶界面來(lái)感受到軟件系統(tǒng)的問(wèn)題的侯谁。此時(shí)最好的入手點(diǎn)當(dāng)然就是重現(xiàn) Bug锌仅,而我們剛說(shuō)過(guò)單元測(cè)試覆蓋不了上至用戶界面的層級(jí),所以重現(xiàn) Bug 都是從驗(yàn)收測(cè)試開(kāi)始的墙贱,由此入手一層層抽絲剝繭热芹,經(jīng)歷集成測(cè)試最終定位到單元測(cè)試。這一趟下來(lái)不但 Bug 解決了惨撇,而且連帶著把一批復(fù)雜的系統(tǒng)交互都用測(cè)試覆蓋了伊脓,這樣用不了多久你就會(huì)發(fā)現(xiàn)該補(bǔ)的測(cè)試也都補(bǔ)的差不多了。
BDD(行為驅(qū)動(dòng)開(kāi)發(fā)魁衙,Behaviour Driven Development)丽旅,比如用戶使用過(guò)程中反饋的Bug,自上而下補(bǔ) Bug 測(cè)試纺棺。
PHP常見(jiàn)的單元測(cè)試工具可參見(jiàn):https://codegeekz.com/12-best-php-automated-test-frameworks/榄笙,此處我們簡(jiǎn)要介紹phpUnit的簡(jiǎn)單實(shí)用過(guò)程。
安裝PHPUnit
訪問(wèn)phpUnit官網(wǎng)https://phpunit.de/下載相應(yīng)版本的phpUnit祷蝌,此處我們通過(guò)Composer方式安裝:
php -r "readfile('https://getcomposer.org/installer');" | php
composer require --dev phpunit/phpunit ^5.7
編寫PHPUnit測(cè)試
?MVC框架下的controller中新建一個(gè)tests文件夾:
1. 針對(duì)類Class的測(cè)試寫在類ClassTest中茅撞; 2. ClassTest(通常)繼承自PHPUnit\Framework\TestCase;3. 測(cè)試都是命令為test*的公用方法巨朦,或者在方法的文檔注釋塊中使用@test標(biāo)注將其標(biāo)記為測(cè)試方法米丘;4. 在測(cè)試方法內(nèi),類似于assetEquals()這樣的斷言方法來(lái)對(duì)實(shí)際值與預(yù)期值的匹配做出斷言糊啡。比如下圖中phpUnit測(cè)試數(shù)組操作:
PHPUnit支持對(duì)測(cè)試方法間顯式的依賴關(guān)系進(jìn)行聲明拄查,這種依賴關(guān)系并不是定義在測(cè)試方法中的執(zhí)行順序中,而是允許生產(chǎn)者返回一個(gè)測(cè)試基準(zhǔn)(fixture)的實(shí)例棚蓄,并將此實(shí)例傳遞給依賴關(guān)系堕扶。
文檔注釋塊中“用@depends標(biāo)注來(lái)表達(dá)依賴關(guān)系”。比如我們對(duì)上圖中的測(cè)試用例做出分離:
TIPS:默認(rèn)情況下梭依,生產(chǎn)者所產(chǎn)生的返回值將“原樣”傳遞給相應(yīng)的消費(fèi)者稍算,這意味著,如果生產(chǎn)者返回的是一個(gè)對(duì)象役拴,那么傳遞給消費(fèi)者的將是一個(gè)指向此對(duì)象的引用糊探,如果需要傳遞對(duì)象的副本而非引用,則應(yīng)當(dāng)用@depends clone替代@depends。
當(dāng)某個(gè)測(cè)試所依賴的測(cè)試失敗時(shí)科平,PHPUnit會(huì)跳過(guò)這個(gè)測(cè)試褥紫,通過(guò)利用測(cè)試之間的依賴關(guān)系,缺陷定位得到了改進(jìn)瞪慧。
對(duì)于有多重依賴的測(cè)試【一對(duì)多】故源,其中第一個(gè)參數(shù)是第一個(gè)生產(chǎn)者提供的基境,第二個(gè)參數(shù)是第二個(gè)生產(chǎn)者提供的基境汞贸,以此類推。
數(shù)據(jù)供給器為測(cè)試方法提供參數(shù)印机,文檔注釋塊“@dataProvider additionProvider”,數(shù)據(jù)供給器方法additionProvider必須聲明為public矢腻,其返回值要么是一個(gè)數(shù)組,其每個(gè)元素也是數(shù)組射赛;要么是一個(gè)實(shí)現(xiàn)了Iterator接口的對(duì)象多柑,在對(duì)他進(jìn)行迭代時(shí)每一步產(chǎn)生一個(gè)數(shù)組。每個(gè)數(shù)組都是測(cè)試數(shù)據(jù)集的一部分瓣距,將以他的內(nèi)容作為參數(shù)來(lái)調(diào)用測(cè)試方法兜叨。
對(duì)異常進(jìn)行測(cè)試:/*** @expectedException InvalidArgumentException*/
對(duì)錯(cuò)誤進(jìn)行測(cè)試:/*** @expectedException PHPUnit\Framework\Error*/
命令行測(cè)試執(zhí)行器
PHPUnit 命令行測(cè)試執(zhí)行器可通過(guò) phpunit 命令調(diào)用秆剪,phpUnit命令不可用時(shí),以PHP5.6版本為例:
wget https://phar.phpunit.de/phpunit-5.7.phar
chmod +x phpunit-5.7.phar
sudo mv phpunit-5.7.phar /usr/local/bin/phpunit-5.7
phpunit-5.7 --version
phpunit-5.7 --help
組織測(cè)試
PHPUnit 的目標(biāo)之一是測(cè)試應(yīng)當(dāng)可組合:我們希望能將任意數(shù)量的測(cè)試以任意組合方式運(yùn)行初嘹,例如,整個(gè)項(xiàng)目的所有測(cè)試沮趣,或者項(xiàng)目中的某個(gè)組件內(nèi)的所有類的測(cè)試屯烦,又或者僅僅某單個(gè)類的測(cè)試。
PHPUnit 支持好幾種不同的方式來(lái)組織測(cè)試以及將它們編排組合成測(cè)試套件房铭。下面介紹了兩種最常用的方法:
用文件系統(tǒng)來(lái)編排測(cè)試套件
最簡(jiǎn)單的大概就是把所有測(cè)試用例源文件放在一個(gè)測(cè)試目錄中驻龟。當(dāng) PHPUnit 命令行測(cè)試執(zhí)行器指向一個(gè)目錄時(shí),它會(huì)在目錄下查找 *Test.php 文通過(guò)對(duì)測(cè)試目錄進(jìn)行遞歸遍歷并運(yùn)行測(cè)試缸匪。
phpunit --bootstrap src/autoload.php tests
用 XML 配置來(lái)編排測(cè)試套件
測(cè)試替身
轉(zhuǎn)自:https://phpunit.de/manual/current/zh_cn/phpunit-book.pdf
https://www.ibm.com/developerworks/cn/opensource/os-cn-php-autotest/
http://www.thinkphp.cn/topic/37779.html