Este pacote está obsoleto, verifique Infecção.
Humbug é uma estrutura de teste de mutação para PHP. Ele está atualmente em desenvolvimento e, embora funcione muito bem, terá arestas que uma equipe de minions está trabalhando duro para resolver. Se cair do portão, você foi avisado;).
$ git remote set-url upstream https://github.com/humbug/humbug.git
Substitua upstream
pelo nome do controle remoto que você usa localmente; upstream
é comumente usado, mas você pode estar usando outra coisa. Você também pode usar um URL diferente (por exemplo, [email protected]:mockery/mockery.git). Execute git remote -v
para ver o que você está realmente usando.
Índice
O teste de mutação é, em poucas palavras, dar aos seus testes de unidade uma chance pelo seu dinheiro. Envolve injetar pequenos defeitos no código-fonte e depois verificar se os testes de unidade foram notados. Se isso acontecer, então seus testes de unidade "mataram" a mutação. Caso contrário, a mutação escapou à detecção. Como os testes unitários têm como objetivo evitar regressões, fazer com que uma regressão real passe despercebida seria uma coisa ruim!
Enquanto a cobertura de código pode informar qual código seus testes estão executando, o teste de mutação tem como objetivo ajudá-lo a avaliar o desempenho real de seus testes de unidade e onde eles podem ser melhorados.
Escrevi com mais detalhes sobre por que vale a pena ter testes de mutação: Mentiras, mentiras malditas e cobertura de código: rumo ao teste de mutação
Humbug é um projeto de código aberto que aceita solicitações pull e problemas de qualquer pessoa. Antes de abrir pull requests, leia nosso breve Guia de Contribuição.
Você pode clonar e instalar as dependências do Humbug usando o Composer:
git clone https://github.com/humbug/humbug.git
cd humbug
/path/to/composer.phar install
O comando humbug está agora em bin/humbug.
Se não quiser rastrear o branch master diretamente, você pode instalar o Humbug phar da seguinte maneira:
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
No Windows, você pode simplesmente fazer download usando um navegador ou do Powershell v3 usando os seguintes comandos onde wget
é um alias para 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
Se você estiver preso ao 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 " )
O phar é assinado com uma chave privada openssl. Você precisará que o arquivo pubkey esteja sempre armazenado ao lado do arquivo phar para poder usá-lo. Se você renomear humbug.phar
para humbug
, por exemplo, renomeie também a chave de humbug.phar.pubkey
para humbug.pubkey
.
Os lançamentos do phar são atualmente feitos manualmente, portanto não serão atualizados com a mesma frequência que o git master. Para atualizar seu phar atual, basta executar:
./humbug.phar self-update
Nota: Usar um phar significa que as correções podem demorar mais para chegar à sua versão, mas há mais garantia de ter uma versão de desenvolvimento estável. A chave pública é baixada apenas uma vez. Ele é reutilizado por autoatualização para verificar versões futuras do phar.
Assim que os lançamentos começarem a se tornar estáveis, haverá um alfa, um beta, um RC e um lançamento final. Seu arquivo phar da trilha de desenvolvimento será atualizado automaticamente até atingir uma versão estável. Se desejar continuar acompanhando os phars do nível de desenvolvimento, você precisará indicar isso usando um dos sinalizadores de estabilidade:
./humbug.phar self-update --dev
Se você tiver algum problema de atualização automática com erros inesperados openssl
ou SSL, certifique-se de ter habilitado a extensão openssl
. No Windows, você pode fazer isso adicionando ou descomentando a seguinte linha no arquivo php.ini
para PHP na linha de comando (se for diferente do arquivo do seu servidor http):
extension=php_openssl.dll
Alguns outros erros de SSL podem surgir devido à falta de certificados. Você pode corrigir isso encontrando a localização deles em seu sistema (por exemplo, C:/xampp/php/ext/cacert.pem
) ou, alternativamente, baixando uma cópia de http://curl.haxx.se/ca/cacert.pem. Em seguida, certifique-se de que a seguinte opção esteja apontando corretamente para este arquivo:
openssl.cafile=C:/path/to/cacert.pem
Devido às dependências do Humbug estarem atreladas a versões recentes, adicionar o Humbug ao compositor.json pode causar conflitos. Os dois métodos de instalação acima são preferidos quando isso ocorre. No entanto, você pode instalá-lo globalmente como qualquer outra ferramenta de uso geral:
composer global require ' humbug/humbug=~1.0@dev '
E se você ainda não fez isso... adicione isto a ~/.bash_profile
(ou ~/.bashrc
):
export PATH= ~ /.composer/vendor/bin: $PATH
Humbug atualmente funciona em PHP 5.4 ou superior.
A farsa ainda está em desenvolvimento, então, para repetir, tome cuidado com as arestas.
Para configurar o humbug no seu projeto você pode executar:
humbug configure
Esta ferramenta fará algumas perguntas necessárias para criar o arquivo de configuração do Humbug ( humbug.json.dist
).
No diretório base do seu projeto crie um arquivo humbug.json.dist
:
{
"timeout" : 10 ,
"source" : {
"directories" : [
"src"
]
} ,
"logs" : {
"text" : "humbuglog.txt" ,
"json" : "humbuglog.json"
}
}
Você pode enviar humbug.json.dist
para seu VCS e substituí-lo localmente por um arquivo humbug.json
.
Edite conforme apropriado. Se você não definir pelo menos um log, informações detalhadas sobre os mutantes escapados não estarão disponíveis. O log de texto é legível por humanos. Se os arquivos de origem existirem no diretório base, ou se os arquivos nos diretórios de origem precisarem ser excluídos, você poderá adicionar padrões de exclusão (aqui está um para arquivos no diretório base onde os diretórios do fornecedor do compositor e dos testes são excluídos):
{
"timeout" : 10 ,
"source" : {
"directories" : [
"."
] ,
"excludes" : [
"vendor" ,
"Tests"
]
} ,
"logs" : {
"text" : "humbuglog.txt"
}
}
Se, a partir do diretório base do seu projeto, você precisar executar testes de outro diretório, poderá sinalizar isso também. Você não deve precisar executar o Humbug a partir de qualquer diretório diferente do diretório base do seu projeto.
{
"chdir" : "tests" ,
"timeout" : 10 ,
"source" : {
"directories" : [
"src"
] ,
}
}
Certifique-se de que todos os seus testes sejam aprovados (testes incompletos e ignorados são permitidos). O Humbug será encerrado se algum de seus testes falhar.
O comando mágico, enquanto estiver no diretório base do seu projeto (usando o download do PHAR) é:
./humbug.phar
ou se você acabou de clonar o Humbug:
../humbug/bin/humbug
ou se você adicionou o Humbug como uma dependência do compositor ao seu projeto:
./vendor/bin/humbug
Em vez de php com a extensão xdebug você também pode executar o Humbug via phpdbg:
phpdbg -qrr humbug.phar
Se tudo correr bem, você obterá algo semelhante a:
_ _ _
| || |_ _ _ __ | |__ _ _ __ _
| __ | || | ' | '_ || / _` |
|_||_|_,_|_|_|_|_.__/_,___, |
|___/
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
Para explicar o resultado do progresso talvez enigmático:
Kills, erros e timeouts são contados como mutações detectadas. Relatamos erros nos logs caso o próprio Humbug tenha encontrado um erro interno, ou seja, um bug a ser relatado como um problema aqui!
Os resultados resumidos do exemplo relataram uma série de pontuações de métricas:
Se você examinar essas métricas, o que mais se destaca é que o MSI de 47% é 18 pontos menor do que a cobertura de código relatada de 65%. Esses testes unitários são muito menos eficazes do que o Code Coverage sozinho poderia detectar.
A interpretação desses resultados requer algum contexto. Os logs listarão todas as mutações não detectadas como diferenças em relação ao código-fonte original. Examiná-los fornecerá mais informações sobre quais mutações específicas não foram detectadas.
O Humbug tem algumas opções de linha de comando dignas de nota, além daquelas normalmente associadas a qualquer aplicativo Symfony Console.
Você pode definir manualmente o limite de tempo limite para qualquer teste:
humbug --timeout=10
Se você estiver interessado apenas em alterar um subconjunto de seus arquivos, poderá passar qualquer número de opções --file
contendo nomes de arquivos simples, globs ou expressões regulares. Basicamente, tudo isso é passado para o método name()
do Symfony Finder.
humbug --file=NewClass.php --file= * Driver.php
Isso não restringe de forma alguma a verificação inicial do Humbug no conjunto de testes geral, que ainda é executado por completo para garantir que todos os testes sejam aprovados corretamente antes de prosseguir.
Se você deseja alterar apenas alguns arquivos específicos, você pode passar qualquer número de opções --path
contendo nomes de arquivo de caminho completo. Esta opção será passada para um filtro Closure
que cruzará os arquivos encontrados usando a opção config e/ou --file
com os arquivos fornecidos por você usando a opção --path
.
humbug --path=src/Data/NewClass.php --path=src/Driver/Driver.php
Nota: Isso não restringe de forma alguma a verificação inicial do Humbug no conjunto de testes geral, que ainda é executado por completo para garantir que todos os testes sejam aprovados corretamente antes de prosseguir.
A Análise Incremental (IA) é um modo de operação experimental inacabado em que os resultados são armazenados em cache localmente entre as execuções e reutilizados onde fizer sentido. Atualmente, este modo opera de forma muito ingênua, eliminando execuções de teste onde tanto o arquivo imediato que está sendo mutado quanto os testes relevantes para uma linha mutada não foram modificados desde a última execução (conforme determinado pela comparação do SHA1 dos arquivos envolvidos).
humbug --incremental
O modo IA oferece um aumento significativo de desempenho para bases de código relativamente estáveis, e você está livre para testá-lo e ver como ele se sai na vida real. No futuro, será necessário levar em conta as alterações nos arquivos que contêm classes pai, características importadas e as classes de suas dependências imediatas, todas as quais têm impacto no comportamento de qualquer objeto.
IA utiliza um cache local permanente, por exemplo, /home/padraic/.humbug
.
O teste de mutação tem sido tradicionalmente lento. O conceito é executar novamente seu conjunto de testes para cada mutação gerada. Para acelerar significativamente as coisas, o Humbug faz o seguinte:
Embora tudo isso acelere o Humbug, esteja ciente de que a execução do Humbug será mais lenta do que o teste de unidade. Um conjunto de testes de 2 segundos pode exigir 30 segundos para testes de mutação. Ou 5 minutos. Tudo depende da interação entre as linhas de código, do número de testes, do nível de cobertura do código e do desempenho do código e dos testes.
O Humbug implementa um conjunto básico de Mutadores, que essencialmente nos informa quando um token PHP específico pode sofrer mutação e também aplica essa mutação a uma matriz de tokens.
Nota: O código-fonte mantido em funções (em vez de métodos de classe) não sofre mutação neste momento.
Aritmética Binária:
Original | Mutado | Original | Mutado |
---|---|---|---|
+ | - | /= | *= |
- | + | %= | *= |
* | / | **= | /= |
/ | * | & | | |
% | * | | | & |
** | / | ^ | & |
+= | -= | ~ | |
-= | += | >> | << |
*= | /= | << | >> |
Substituição booleana:
Isso abrange temporariamente mutadores lógicos.
Original | Mutado |
---|---|
verdadeiro | falso |
falso | verdadeiro |
&& | || |
|| | && |
e | ou |
ou | e |
! |
Limites Condicionais:
Original | Mutado |
---|---|
> | >= |
< | <= |
>= | > |
<= | < |
Condicionais Negadas:
Original | Mutado | Original | Mutado |
---|---|---|---|
== | != | > | <= |
!= | == | < | >= |
<> | == | >= | < |
=== | !== | <= | > |
!== | === |
Incrementos:
Original | Mutado |
---|---|
++ | -- |
-- | ++ |
Valores de retorno:
Original | Mutado | Original | Mutado |
---|---|---|---|
retornar verdadeiro; | retornar falso; | retornar 1,0>; | retornar -( + 1); |
retornar falso; | retornar verdadeiro; | retorne $isto; | retornar nulo; |
retornar 0; | retornar 1; | função de retorno(); | função(); retornar nulo; |
retornar ; | retornar 0; | retornar nova classe; | nova classe; retornar nulo; |
retornar 0,0; | retornar 1,0; | retornar ( Anything ); | ( Anything ); retornar nulo; |
retornar 1,0; | retornar 0,0; |
Números Literais:
Original | Mutado |
---|---|
0 | 1 |
1 | 0 |
Int > 1 | Int + 1 |
Flutuar >= 1 / <= 2 | Flutuar + 1 |
Flutuar > 2 | 1 |
Se declarações:
Todas as instruções if são amplamente cobertas por modificadores anteriores, mas há casos especiais, como o uso de funções nativas ou métodos de classe sem quaisquer comparações ou operações, por exemplo, is_int()
ou in_array()
. Isso não cobriria funções definidas em arquivos, pois elas não existem até o tempo de execução (outra coisa para trabalhar!).
Original | Mutado |
---|---|
se(é_int(1)) | if(!is_int(1)) |
Mais Mutadores serão adicionados ao longo do tempo.
bin/humbug stats ../my-project/humbuglog.json ../my-project/list-of-classes.txt --skip-killed=yes [-vvv]
Analisa estatísticas de humbuglog.json ou de seu log JSON com nome personalizado.
Referência 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
Isso pode ser testado no próprio humbug, executando no diretório do humbug:
bin/farsa bin/fraude estatísticas [-vvv]
Esta é uma pequena lista de problemas conhecidos:
Cortesia de Craig Davis, que viu potencial em um repositório antes vazio: 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 .::::::::::::::::::::::::::::
:::::::`"????"".::::::::::::::::::::::::::::::