該軟體包已被棄用,請查看感染。
Humbug 是 PHP 的突變測試框架。它目前正在開發中,因此,雖然它實際上運行得很好,但它仍然存在一些缺陷,一群小小兵正在努力解決這些問題。如果它掉出門外,我們已警告您;)。
$ git remote set-url upstream https://github.com/humbug/humbug.git
將upstream
替換為您本地使用的遙控器的名稱; upstream
是常用的,但您可能正在使用其他東西。您也可以使用不同的 URL(例如 [email protected]:mockery/mockery.git)。執行git remote -v
查看您實際使用的內容。
目錄
簡而言之,突變測試就是讓你的單元測試物有所值。它涉及將小缺陷注入原始程式碼,然後檢查單元測試是否注意到。如果確實如此,那麼您的單元測試已經「殺死」了該突變。如果不是,則該突變就逃脫了檢測。由於單元測試的目的是防止回歸,因此沒有註意到真正的回歸通過將是一件壞事!
程式碼覆蓋率可以告訴您測試正在執行哪些程式碼,而突變測試旨在幫助您判斷單元測試的實際執行情況以及可以改進的地方。
我已經更詳細地寫了為什麼突變測試值得擁有:謊言,該死的謊言和程式碼覆蓋率:走向突變測試
Humbug 是一個開源項目,歡迎任何人提出拉取請求和問題。在打開拉取請求之前,請閱讀我們簡短的貢獻指南。
您可以使用 Composer 複製並安裝 Humbug 的依賴項:
git clone https://github.com/humbug/humbug.git
cd humbug
/path/to/composer.phar install
humbug 指令現在位於 bin/humbug。
如果你不想直接追蹤master分支,你可以安裝Humbug phar,如下所示:
wget https://padraic.github.io/humbug/downloads/humbug.phar
wget https://padraic.github.io/humbug/downloads/humbug.phar.pubkey
# If you wish to make humbug.phar directly executable
chmod +x humbug.phar
在 Windows 上,您可以使用瀏覽器或使用下列命令從 Powershell v3 下載,其中wget
是Invoke-WebRequest
的別名:
wget https://padraic.github.io/humbug/downloads/humbug.phar -OutFile humbug.phar
wget https://padraic.github.io/humbug/downloads/humbug.phar.pubkey -OutFile humbug.phar.pubkey
如果您無法使用 Powershell v2:
$client = new-object System.Net.WebClient
$client .DownloadFile( " https://padraic.github.io/humbug/downloads/humbug.phar " , " humbug.phar " )
$client .DownloadFile( " https://padraic.github.io/humbug/downloads/humbug.phar.pubkey " , " humbug.phar.pubkey " )
phar 使用 openssl 私鑰進行簽署。您需要始終將 pubkey 檔案儲存在 phar 檔案旁邊才能使用它。例如,如果將humbug.phar
重新命名為humbug
,則也將金鑰從humbug.phar.pubkey
重新命名為humbug.pubkey
。
phar 版本目前是手動完成的,因此它們不會以與 git master 相同的頻率更新。要更新當前的 Phar,只需運行:
./humbug.phar self-update
注意:使用 phar 意味著修復可能需要更長的時間才能到達您的版本,但可以更好地保證擁有穩定的開發版本。公鑰僅下載一次。透過自我更新重複使用它來驗證未來的 Phar 版本。
一旦版本開始趨於穩定,就會有 alpha、beta、RC 和最終版本。您的開發追蹤 phar 檔案將自動自我更新,直到達到穩定版本。如果您希望繼續追蹤開發層級階段,您將需要使用穩定性標誌之一來表明這一點:
./humbug.phar self-update --dev
如果您在自我更新時遇到任何意外openssl
或 SSL 錯誤的問題,請確保您已啟用openssl
擴充功能。在 Windows 上,您可以透過在命令列上新增或取消註解 PHP 的php.ini
檔案中的以下行來執行此操作(如果與您的 http 伺服器的檔案不同):
extension=php_openssl.dll
由於缺少證書,可能會出現某些其他 SSL 錯誤。您可以透過尋找它們在系統上的位置(例如C:/xampp/php/ext/cacert.pem
)或從 http://curl.haxx.se/ca/cacert.pem 下載副本來修正此問題。然後確保以下選項正確指向該文件:
openssl.cafile=C:/path/to/cacert.pem
由於 Humbug 的依賴項與最新版本掛鉤,因此將 Humbug 新增至composer.json 可能會引起衝突。當發生這種情況時,首選上述兩種安裝方法。但是,您可以像任何其他通用工具一樣全域安裝它:
composer global require ' humbug/humbug=~1.0@dev '
如果您以前沒有這樣做過...將其添加到~/.bash_profile
(或~/.bashrc
):
export PATH= ~ /.composer/vendor/bin: $PATH
Humbug 目前適用於 PHP 5.4 或更高版本。
Humbug 仍在開發中,因此,重複一遍,要小心粗糙的邊緣。
要在專案中配置 humbug,您可以運行:
humbug configure
該工具將詢問創建 Humbug 配置檔案 ( humbug.json.dist
) 所需的一些問題。
在專案的基本目錄中建立一個humbug.json.dist
檔案:
{
"timeout" : 10 ,
"source" : {
"directories" : [
"src"
]
} ,
"logs" : {
"text" : "humbuglog.txt" ,
"json" : "humbuglog.json"
}
}
您可以將humbug.json.dist
提交到 VCS 並使用humbug.json
檔案在本地覆蓋它。
根據需要進行編輯。如果您沒有定義至少一個日誌,則有關逃脫突變體的詳細資訊將不可用。文字日誌是人類可讀的。如果來源檔案存在於基本目錄中,或者必須排除來源目錄中的文件,則可以新增排除模式(這是針對基本目錄中的檔案的排除模式,其中排除了composer供應商和測試目錄):
{
"timeout" : 10 ,
"source" : {
"directories" : [
"."
] ,
"excludes" : [
"vendor" ,
"Tests"
]
} ,
"logs" : {
"text" : "humbuglog.txt"
}
}
如果您必須從專案的基底目錄中從另一個目錄執行測試,那麼您也可以發出訊號。您不需要從專案基目錄以外的任何目錄執行 Humbug。
{
"chdir" : "tests" ,
"timeout" : 10 ,
"source" : {
"directories" : [
"src"
] ,
}
}
確保您的測試全部處於通過狀態(允許不完整和跳過的測試)。如果您的任何測試失敗,Humbug 就會退出。
在專案的基本目錄中(使用 PHAR 下載)的神奇命令是:
./humbug.phar
或者如果您剛剛克隆了 Humbug:
../humbug/bin/humbug
或者如果您將 Humbug 作為作曲家依賴項添加到您的專案中:
./vendor/bin/humbug
您也可以透過 phpdbg 運行 Humbug,而不是帶有 xdebug 擴充功能的 php:
phpdbg -qrr humbug.phar
如果一切順利,您將得到類似以下內容的資訊:
_ _ _
| || |_ _ _ __ | |__ _ _ __ _
| __ | || | ' | '_ || / _` |
|_||_|_,_|_|_|_|_.__/_,___, |
|___/
Humbug version 1.0-dev
Humbug running test suite to generate logs and code coverage data...
361 [==========================================================] 28 secs
Humbug has completed the initial test run successfully.
Tests: 361 Line Coverage: 64.86%
Humbug is analysing source files...
Mutation Testing is commencing on 78 files...
(.: killed, M: escaped, S: uncovered, E: fatal error, T: timed out)
.....M.M..EMMMMMSSSSMMMMMSMMMMMSSSE.ESSSSSSSSSSSSSSSSSM..M.. | 60 ( 7/78)
...MM.ES..SSSSSSSSSS...MMM.MEMME.SSSS.............SSMMSSSSM. | 120 (12/78)
M.M.M...TT.M...T.MM....S.....SSS..M..SMMSM...........M...... | 180 (17/78)
MM...M...ESSSEM..MMM.M.MM...SSS.SS.M.SMMMMMMM..SMMMMS....... | 240 (24/78)
.........SMMMSMMMM.MM..M.SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS | 300 (26/78)
SSSSSSSSM..E....S......SS......M.SS..S..M...SSSSSSSS....MMM. | 360 (37/78)
.M....MM..SM..S..SSSSSSSS.EM.S.E.M............M.....M.SM.M.M | 420 (45/78)
..M....MMS...MMSSS................M.....EME....SEMS...SSSSSS | 480 (52/78)
SSSSS.EMSSSSM..M.MMMM...SSE.....MMM.M..MM..MSSSSSSSSSSSSSSSS | 540 (60/78)
SSS....SSSSSSSSMM.SSS..........S..M..MSSMS.SSSSSSSSSSSSSSSSS | 600 (68/78)
......E...M..........SM.....M..MMMMM.MMMMMSSSSSSSM.SS
653 mutations were generated:
284 mutants were killed
218 mutants were not covered by tests
131 covered mutants were not detected
17 fatal errors were encountered
3 time outs were encountered
Metrics:
Mutation Score Indicator (MSI): 47%
Mutation Code Coverage: 67%
Covered Code MSI: 70%
Remember that some mutants will inevitably be harmless (i.e. false positives).
Humbug results are being logged as JSON to: log.json
Humbug results are being logged as TEXT to: log.txt
解釋一下可能神秘的進度輸出:
殺死、錯誤和超時都被計算為檢測到的突變。如果 Humbug 本身遇到內部錯誤,即在此處將錯誤報告為問題,我們會在日誌中報告錯誤!
範例摘要結果報告了許多指標分數:
如果您檢查這些指標,您會發現最突出的問題是 47% 的 MSI 比報告的 65% 的程式碼覆蓋率低 18 個百分點。這些單元測試的效果遠不如單獨的程式碼覆蓋率所能偵測到的有效。
解釋這些結果需要一些背景。日誌將列出所有未檢測到的突變,作為與原始原始碼的差異。檢查這些將進一步了解哪些特定突變未被檢測到。
除了通常與任何 Symfony 控制台應用程式關聯的命令列選項外,Humbug 還有一些值得注意的命令列選項。
您可以手動設定任何單一測試的逾時閾值:
humbug --timeout=10
如果您只對更改檔案的子集感興趣,則可以傳遞任意數量的--file
選項,其中包含簡單檔案名稱、glob 或正規表示式。基本上,這些都被傳遞給 Symfony Finder 的name()
方法。
humbug --file=NewClass.php --file= * Driver.php
這絕不限制整個測試套件的初始 Humbug 檢查,該測試套件仍然完整執行,以確保所有測試在繼續之前都正確通過。
如果您只想更改幾個特定文件,則可以傳遞任意數量的包含完整路徑文件名的--path
選項。此選項將傳遞到過濾器Closure
,它將使用 config 和/或--file
選項找到的檔案與使用--path
選項提供的檔案相交。
humbug --path=src/Data/NewClass.php --path=src/Driver/Driver.php
注意:這絕不限制整個測試套件的初始 Humbug 檢查,該測試套件仍會完整執行,以確保所有測試在繼續之前都正確通過。
增量分析 (IA) 是一種實驗性的未完成操作模式,其中結果在運行之間本地緩存,並在有意義的地方重複使用。目前,此模式透過消除測試運行來非常簡單地運行,其中自上次運行以來,正在變異的直接文件和變異行的相關測試都沒有被修改(通過比較所涉及文件的 SHA1 確定)。
humbug --incremental
IA 模式為相對穩定的程式碼庫提供了顯著的效能提升,您可以自由地測試它並了解它在現實生活中的表現。將來,它確實需要考慮包含父類別、匯入特徵及其直接依賴項的類別的檔案中的更改,所有這些都會對任何給定物件的行為產生影響。
IA 使用本地永久緩存,例如/home/padraic/.humbug
。
突變測試傳統上進展緩慢。其概念是針對產生的每個突變重新運行測試套件。為了顯著加快速度,Humbug 執行以下操作:
雖然所有這些都會加快 Humbug 的速度,但請注意,Humbug 的運行速度會比單元測試慢。 2 秒的測試套件可能需要 30 秒來進行突變測試。或5分鐘。這一切都取決於程式碼行之間的相互作用、測試數量、程式碼覆蓋層級以及程式碼和測試的效能。
Humbug 實作了一套基本的 Mutators,它本質上告訴我們何時可以對特定的 PHP 令牌進行突變,並將該突變應用於令牌數組。
注意:函數(而不是類別方法)中保存的原始程式碼此時不會發生變化。
二進制算術:
原來的 | 變異的 | 原來的 | 變異的 |
---|---|---|---|
+ | - | /= | *= |
- | + | %= | *= |
* | / | **= | /= |
/ | * | & | | |
% | * | | | & |
** | / | ^ | & |
+= | -= | ~ | |
-= | += | >> | << |
*= | /= | << | >> |
布林替換:
這暫時包含邏輯變異器。
原來的 | 變異的 |
---|---|
真的 | 錯誤的 |
錯誤的 | 真的 |
&& | || |
|| | && |
和 | 或者 |
或者 | 和 |
! |
條件邊界:
原來的 | 變異的 |
---|---|
> | >= |
< | <= |
>= | > |
<= | < |
否定條件句:
原來的 | 變異的 | 原來的 | 變異的 |
---|---|---|---|
== | != | > | <= |
!= | == | < | >= |
<> | == | >= | < |
=== | !== | <= | > |
!== | === |
增量:
原來的 | 變異的 |
---|---|
++ | -- |
-- | ++ |
傳回值:
原來的 | 變異的 | 原來的 | 變異的 |
---|---|---|---|
返回真; | 返回假; | 返回1.0>; | 返回-(+1); |
返回假; | 返回真; | 返回$這個; | 返回空值; |
返回0; | 返回1; | 返回函數(); | 功能();返回空值; |
返回 ; | 返回0; | 返回新類別; | 新班級;返回空值; |
返回0.0; | 返回 1.0; | 返回( Anything ); | ( Anything );返回空值; |
返回 1.0; | 返回0.0; |
文字數字:
原來的 | 變異的 |
---|---|
0 | 1 |
1 | 0 |
智力 > 1 | 智力+1 |
浮點數 >= 1 / <= 2 | 浮動+1 |
浮動 > 2 | 1 |
如果語句:
所有 if 語句大部分都被先前的變異器覆蓋,但也有一些特殊情況,例如使用本機函數或類別方法而不進行任何比較或操作,例如is_int()
或in_array()
。這不會涵蓋文件中定義的函數,因為它們直到運行時才存在(還有其他工作要做!)。
原來的 | 變異的 |
---|---|
如果(is_int(1)) | if(!is_int(1)) |
隨著時間的推移,將會添加更多的 Mutators。
bin/humbug stats ../my-project/humbuglog.json ../my-project/list-of-classes.txt --skip-killed=yes [-vvv]
解析 humbuglog.json 或自訂命名 JSON 日誌中的統計資料。
CLI 參考:
humbug stats [humbuglog.json location] [class list location] [--skip-killed = yes] [-vvv]
humbuglog.json location, defaults to ./humbuglog.json
class list location, a path to a text file containing full class names, one per line.
only this files-related stats would be shown
--skip-killed=yes is used to completely skip output of "killed" section
various verbosity levels define amount of info to be displayed:
by default, there's one line per class with amount of mutants killed/escaped/errored/timed out (depending on output section)
-v adds one line per each mutant with line number and method name
-vv adds extra line for each mutant, displaying diff view of line mutant is detected in
-vvv shows full diff with several lines before and after
這可以透過在 humbug 的目錄中運行來在 humbug 本身上進行測試:
bin/humbug bin/humbug 統計資料 [-vvv]
這是已知問題的簡短清單:
由 Craig Davis 提供,他看到了曾經空的存儲庫的潛力:P。
.:::::::::::...
.::::::::::::::::::::.
.::::::::::::::::::::::::.
::::::::::::::::::::::::::::.
::::::::::::::::::::::::::::::: .,uuu ...
:::::::::::::::::::::::::::::::: dHHHHHLdHHHHb
....:::::::'` ::::::::::::::::::' uHHHHHHHHHHHHHF
.uHHHHHHHHH' ::::::::::::::`. uHHHHHHHHHHHHHP"
HHHHHHHHHHH `:::::::::::',dHHuHHHHHHHHP".g@@g
J"HHHHHHHHHP 4H ::::::::' u$$$.
".HHHHHHHHP" .,uHP :::::' uHHHHHHHHHHP"",e$$$$$c
HHHHHHHF' dHHHHf `````.HHHHHHHHHHP",d$$$$$$$P%C
.dHHHP"" JHHHHbuuuu,JHHHHHHHHP",d$$$$$$$$$e=,z$$$$$$$$ee..
"" .HHHHHHHHHHHHHHHHHP",gdP" ..3$$$Jd$$$$$$$$$$$$$$e.
dHHHHHHHHHHHHHHP".edP " .zd$$$$$$$$$$$"3$$$$$$$$c
`???""??HHHHP",e$$F" .d$,?$$$$$$$$$$$$$F d$$$$$$$$F"
?be.eze$$$$$".d$$$$ $$$E$$$$P".,ede`?$$$$$$$$
4."?$$$$$$$ z$$$$$$ $$$$r.,.e ?$$$$ $$$$$$$$$
'$c "$$$$ .d$$$$$$$ 3$$$.$$$$ 4$$$ d$$$$P"`,,
"""- "$$".`$$" " $$f,d$$P".$$P zeee.zd$$$$$.
ze. .C$C"=^" ..$$$$$$P".$$$'e$$$$$P?$$$$$$
.e$$$$$$$"="$f",c,3eee$$$$$$$$P $$$P'd$$$$"..::.."?$%
4d$$$P d$$$dF.d$$$$$$$$$$$$$$$$f $$$ d$$$" :::::::::.
$$$$$$ d$$$$$ $$$$$$$$$$$$$$$$$$ J$$",$$$'.::::::::::::
"$$$$$$ ?$$$$ d$$$$$$$$$$$$$$$P".dP'e$$$$':::::::::::::::
4$$$$$$c $$$$b`$$$$$$$$$$$P"",e$$",$$$$$' ::::::::::::::::
' ?"?$$$b."$$$$.?$$$$$$P".e$$$$F,d$$$$$F ::::::::::::::::::
"?$$bc."$b.$$$$F z$$P?$$",$$$$$$$ ::::::::::::::::::::
`"$$c"?$$$".$$$)e$$F,$$$$$$$' ::::::::::::::::::::
':. "$b...d$$P4$$$",$$$$$$$" :::::::::::::::::::::
':::: "$$$$$".,"".d$$$$$$$F ::::::::::::::::::::::
:::: be."".d$$$4$$$$$$$$F :::::::::::::::::::::::
:::: "??$$$$$$$$$$?$P" :::::::::::::::::::::::::
:::::: ?$$$$$$$$f .::::::::::::::::::::::::::::
:::::::`"????"".::::::::::::::::::::::::::::::