Este paquete está en desuso; en su lugar, consulte Infección.
Humbug es un marco de prueba de mutaciones para PHP. Actualmente está en desarrollo y, si bien funciona bastante bien, tendrá asperezas que un equipo de minions está trabajando arduamente para solucionar. Si se cae por la puerta, estás advertido;).
$ git remote set-url upstream https://github.com/humbug/humbug.git
Reemplace upstream
con el nombre del control remoto que usa localmente; upstream
se usa comúnmente, pero es posible que estés usando algo más. También puede utilizar una URL diferente (por ejemplo, [email protected]:mockery/mockery.git). Ejecute git remote -v
para ver qué estás usando realmente.
Tabla de contenido
Las pruebas de mutación son, en pocas palabras, darle una oportunidad a las pruebas unitarias. Implica inyectar pequeños defectos en el código fuente y luego verificar si las pruebas unitarias lo notaron. Si es así, entonces sus pruebas unitarias han "matado" la mutación. De lo contrario, la mutación ha escapado a la detección. Como las pruebas unitarias están destinadas a evitar regresiones, ¡que una regresión real pase desapercibida sería algo malo!
Mientras que la cobertura de código puede indicarle qué código están ejecutando sus pruebas, las pruebas de mutación están destinadas a ayudarle a juzgar qué tan bien se desempeñan realmente sus pruebas unitarias y dónde podrían mejorarse.
He escrito con más detalle sobre por qué vale la pena realizar pruebas de mutaciones: Mentiras, malditas mentiras y cobertura de código: hacia las pruebas de mutaciones
Humbug es un proyecto de código abierto que acepta solicitudes de extracción y problemas de cualquier persona. Antes de abrir solicitudes de extracción, lea nuestra breve Guía de contribución.
Puedes clonar e instalar las dependencias de Humbug usando Composer:
git clone https://github.com/humbug/humbug.git
cd humbug
/path/to/composer.phar install
El comando humbug ahora está en bin/humbug.
Si no desea rastrear la rama maestra directamente, puede instalar Humbug phar de la siguiente manera:
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
En Windows, puede descargar usando un navegador o desde Powershell v3 usando los siguientes comandos donde wget
es un 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
Si estás atrapado con 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 " )
El phar está firmado con una clave privada de openssl. Necesitará que el archivo pubkey esté almacenado junto al archivo phar en todo momento para poder usarlo. Si cambia el nombre humbug.phar
a humbug
, por ejemplo, cambie también el nombre de la clave de humbug.phar.pubkey
a humbug.pubkey
.
Actualmente, las versiones de phar se realizan manualmente, por lo que no se actualizarán con la misma frecuencia que git master. Para actualizar su phar actual, simplemente ejecute:
./humbug.phar self-update
Nota: Usar un phar significa que las correcciones pueden tardar más en llegar a su versión, pero hay más seguridad de tener una versión de desarrollo estable. La clave pública se descarga solo una vez. Se reutiliza mediante actualización automática para verificar futuras versiones de phar.
Una vez que los lanzamientos comiencen hacia la versión estable, habrá una versión alfa, beta, RC y una versión final. Su archivo phar de seguimiento de desarrollo se actualizará automáticamente hasta que alcance una versión estable. Si desea continuar rastreando los phars del nivel de desarrollo, deberá indicarlo usando uno de los indicadores de estabilidad:
./humbug.phar self-update --dev
Si tiene algún problema al actualizarse automáticamente con errores inesperados openssl
o SSL, asegúrese de haber habilitado la extensión openssl
. En Windows, puede hacer esto agregando o descomentando la siguiente línea en el archivo php.ini
para PHP en la línea de comando (si es diferente al archivo de su servidor http):
extension=php_openssl.dll
Es posible que surjan otros errores de SSL debido a la falta de certificados. Puede rectificar esto buscando su ubicación en su sistema (por ejemplo, C:/xampp/php/ext/cacert.pem
) o, alternativamente, descargando una copia desde http://curl.haxx.se/ca/cacert.pem. Luego asegúrese de que la siguiente opción apunte correctamente a este archivo:
openssl.cafile=C:/path/to/cacert.pem
Debido a que las dependencias de Humbug están vinculadas a versiones recientes, agregar Humbug a Composer.json puede generar conflictos. Cuando esto ocurre, se prefieren los dos métodos de instalación anteriores. Sin embargo, puedes instalarlo globalmente como cualquier otra herramienta de propósito general:
composer global require ' humbug/humbug=~1.0@dev '
Y si no lo ha hecho anteriormente... agregue esto a ~/.bash_profile
(o ~/.bashrc
):
export PATH= ~ /.composer/vendor/bin: $PATH
Humbug actualmente funciona en PHP 5.4 o superior.
Humbug todavía está en desarrollo así que, repito, tenga cuidado con las asperezas.
Para configurar humbug en su proyecto puede ejecutar:
humbug configure
Esta herramienta hará algunas preguntas necesarias para crear el archivo de configuración de Humbug ( humbug.json.dist
).
En el directorio base de su proyecto, cree un archivo humbug.json.dist
:
{
"timeout" : 10 ,
"source" : {
"directories" : [
"src"
]
} ,
"logs" : {
"text" : "humbuglog.txt" ,
"json" : "humbuglog.json"
}
}
Puede enviar humbug.json.dist
a su VCS y anularlo localmente con un archivo humbug.json
.
Edite según corresponda. Si no define al menos un registro, la información detallada sobre los mutantes escapados no estará disponible. El registro de texto es legible por humanos. Si los archivos de origen existen en el directorio base, o los archivos en los directorios de origen deben excluirse, puede agregar patrones de exclusión (aquí hay uno para los archivos en el directorio base donde se excluyen los directorios del proveedor del compositor y de Pruebas):
{
"timeout" : 10 ,
"source" : {
"directories" : [
"."
] ,
"excludes" : [
"vendor" ,
"Tests"
]
} ,
"logs" : {
"text" : "humbuglog.txt"
}
}
Si, desde el directorio base de su proyecto, debe ejecutar pruebas desde otro directorio, también puede indicarlo. No debería necesitar ejecutar Humbug desde ningún directorio que no sea el directorio base de su proyecto.
{
"chdir" : "tests" ,
"timeout" : 10 ,
"source" : {
"directories" : [
"src"
] ,
}
}
Asegúrese de que todos sus exámenes estén aprobados (se permiten exámenes incompletos y omitidos). Humbug se cerrará si alguna de sus pruebas falla.
El comando mágico, mientras se encuentra en el directorio base de su proyecto (usando la descarga PHAR) es:
./humbug.phar
o si acabas de clonar Humbug:
../humbug/bin/humbug
o si agregaste Humbug como una dependencia del compositor a tu proyecto:
./vendor/bin/humbug
En lugar de php con la extensión xdebug, también puedes ejecutar Humbug mediante phpdbg:
phpdbg -qrr humbug.phar
Si todo ha ido bien, obtendrás algo similar 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 el resultado de progreso quizás críptico:
Las muertes, los errores y los tiempos de espera se cuentan como mutaciones detectadas. Informamos errores en los registros en caso de que Humbug haya encontrado un error interno, es decir, un error que se informará como un problema aquí.
Los resultados del resumen del ejemplo informaron una serie de puntuaciones de métricas:
Si examina estas métricas, el problema más destacado es que el MSI del 47 % es 18 puntos inferior a la cobertura de código informada del 65 %. Estas pruebas unitarias son mucho menos efectivas de lo que la Cobertura de Código podría detectar por sí sola.
La interpretación de estos resultados requiere algo de contexto. Los registros enumerarán todas las mutaciones no detectadas como diferencias con el código fuente original. Examinarlos proporcionará más información sobre qué mutaciones específicas no se detectaron.
Humbug tiene algunas opciones de línea de comando destacadas, distintas de las normalmente asociadas con cualquier aplicación de consola Symfony.
Puede configurar manualmente el umbral de tiempo de espera para cualquier prueba individual:
humbug --timeout=10
Si solo está interesado en mutar un subconjunto de sus archivos, puede pasar cualquier cantidad de opciones --file
que contengan nombres de archivos simples, globos o expresiones regulares. Básicamente, todos estos se pasan al método name()
de Symfony Finder.
humbug --file=NewClass.php --file= * Driver.php
Esto de ninguna manera restringe la verificación inicial de Humbug en el conjunto de pruebas general, que aún se ejecuta en su totalidad para garantizar que todas las pruebas pasen correctamente antes de continuar.
Si desea mutar solo unos pocos archivos específicos, puede pasar cualquier cantidad de opciones --path
que contengan los nombres de los archivos de ruta completos. Esta opción se pasará a un filtro Closure
que intersectará los archivos encontrados usando la opción config y/o --file
con los archivos proporcionados por usted usando la opción --path
.
humbug --path=src/Data/NewClass.php --path=src/Driver/Driver.php
Nota: Esto de ninguna manera restringe la verificación inicial de Humbug en el conjunto de pruebas general, que aún se ejecuta en su totalidad para garantizar que todas las pruebas se pasen correctamente antes de continuar.
El análisis incremental (IA) es un modo de operación experimental inacabado donde los resultados se almacenan en caché localmente entre ejecuciones y se reutilizan cuando tiene sentido. En la actualidad, este modo funciona de manera muy ingenua al eliminar las ejecuciones de prueba en las que tanto el archivo inmediato que se está mutando como las pruebas relevantes para una línea mutada no se han modificado desde la última ejecución (según lo determinado comparando el SHA1 de los archivos involucrados).
humbug --incremental
El modo IA ofrece un aumento significativo del rendimiento para bases de código relativamente estables, y usted es libre de probarlo y ver cómo funciona en la vida real. En el futuro, necesitará tener en cuenta los cambios en los archivos que contienen clases principales, rasgos importados y las clases de sus dependencias inmediatas, todo lo cual tiene un impacto en el comportamiento de cualquier objeto determinado.
IA utiliza un caché permanente local, por ejemplo, /home/padraic/.humbug
.
Las pruebas de mutación han sido tradicionalmente lentas. El concepto es volver a ejecutar su conjunto de pruebas para cada mutación generada. Para acelerar significativamente las cosas, Humbug hace lo siguiente:
Si bien todo esto acelera Humbug, tenga en cuenta que una ejecución de Humbug será más lenta que una prueba unitaria. Un conjunto de pruebas de 2 segundos puede requerir 30 segundos para la prueba de mutación. O 5 minutos. Todo depende de la interacción entre líneas de código, la cantidad de pruebas, el nivel de cobertura del código y el rendimiento tanto del código como de las pruebas.
Humbug implementa un conjunto básico de mutadores, que esencialmente nos dice cuándo se puede mutar un token PHP en particular y también aplica esa mutación a una serie de tokens.
Nota: El código fuente contenido dentro de funciones (en lugar de métodos de clase) no está mutado en este momento.
Aritmética binaria:
Original | mutado | Original | mutado |
---|---|---|---|
+ | - | /= | *= |
- | + | %= | *= |
* | / | **= | /= |
/ | * | & | | |
% | * | | | & |
** | / | ^ | & |
+= | -= | ~ | |
-= | += | >> | << |
*= | /= | << | >> |
Sustitución booleana:
Esto abarca temporalmente a los mutadores lógicos.
Original | mutado |
---|---|
verdadero | FALSO |
FALSO | verdadero |
&& | || |
|| | && |
y | o |
o | y |
! |
Límites condicionales:
Original | mutado |
---|---|
> | >= |
< | <= |
>= | > |
<= | < |
Condicionales negados:
Original | mutado | Original | mutado |
---|---|---|---|
== | != | > | <= |
!= | == | < | >= |
<> | == | >= | < |
=== | !== | <= | > |
!== | === |
Incrementos:
Original | mutado |
---|---|
++ | -- |
-- | ++ |
Valores de retorno:
Original | mutado | Original | mutado |
---|---|---|---|
devolver verdadero; | devolver falso; | devolver 1.0>; | retorno -( + 1); |
devolver falso; | devolver verdadero; | devolver $esto; | devolver nulo; |
devolver 0; | devolver 1; | función de retorno(); | función(); devolver nulo; |
devolver ; | devolver 0; | devolver nueva Clase; | nueva clase; devolver nulo; |
devolver 0,0; | devolver 1,0; | retorno ( Anything ); | ( Anything ); devolver nulo; |
devolver 1,0; | devolver 0,0; |
Números literales:
Original | mutado |
---|---|
0 | 1 |
1 | 0 |
Int > 1 | Ent + 1 |
Flotante >= 1 / <= 2 | Flotador + 1 |
Flotar > 2 | 1 |
Si declaraciones:
Todas las declaraciones if están cubiertas en gran medida por mutadores anteriores, pero hay casos especiales como el uso de funciones nativas o métodos de clase sin comparaciones u operaciones, por ejemplo, is_int()
o in_array()
. Esto no cubriría las funciones definidas en archivos ya que no existen hasta el tiempo de ejecución (¡algo más en lo que trabajar!).
Original | mutado |
---|---|
si(es_int(1)) | si(!is_int(1)) |
Se agregarán más mutadores con el tiempo.
bin/humbug stats ../my-project/humbuglog.json ../my-project/list-of-classes.txt --skip-killed=yes [-vvv]
Analiza las estadísticas de humbuglog.json o su registro JSON con nombre personalizado.
Referencia 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
Esto se puede probar en el propio humbug, ejecutándolo en el directorio de humbug:
bin/estadísticas de estupideces bin/estadísticas de estupideces [-vvv]
Esta es una breve lista de problemas conocidos:
Cortesía de Craig Davis, que vio potencial en un repositorio que alguna vez estuvo vacío: 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 .::::::::::::::::::::::::::::
:::::::`"????"".::::::::::::::::::::::::::::::