who watches the watchmen? - mutation testing
TRANSCRIPT
Who watches the watchmen?
Rafael Vindel Amor
Consultor Tecnológico en @autentia
@rafaelvindel
José Luis Rodríguez Villapecellín
Consultor Tecnológico en @autentia
@jlrv
Contexto de las Pruebas
¿Qué son las Pruebas?
Las pruebas son el proceso de encontrar errores en un
determinado programa.
¿Qué tipos de pruebas hay?
https://martinfowler.com/articles/microservice-testing/#conclusion-summary
@jlrv | @rafaelvindel | @MalagaJUG
¿para qué sirven?
FAVORECEN EL CAMBIO
FACILITAN LA INTEGRACIÓN
SIRVEN COMO DOCUMENTACIÓN
AUMENTAN LA CALIDAD
@jlrv | @rafaelvindel | @MalagaJUG
Cobertura, ¿truco o trato?@Testpublic void is_special_should_return_true_given_an_specific_date() { SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); Date specialDate = dateFormat.parse("26/09/1985");
sut.isSpecialDate(specialDate);}
@jlrv | @rafaelvindel | @MalagaJUG
¿Es la cobertura una medida real de
calidad?
Somos buenos programadores, ¿verdad?
P
R1
R2
...
Rn
P’
@jlrv | @rafaelvindel | @MalagaJUG
¿HA sido probado a fondo?
¿Son unas pruebas adecuadas?
¿Son unas pruebas de calidad?
Mutation testing
¿Qué es el Mutation Testing?
Técnica que nos ayuda a mejorar nuestras pruebas y medir su calidad frente a la
cobertura tradicional.
¿Cómo funciona?Se realizan cambios en el código, mutaciones, y se ejecutan las pruebas:
Si las pruebas pasan, el mutante sobrevive.
Si las pruebas fallan, el mutante muere.
Al final, nuestras pruebas deberían eliminar todas las mutaciones.
@jlrv | @rafaelvindel | @MalagaJUG
¿Qué son las mutaciones?× Modificar operadores
× Modificar constantes
× Modificar variables
× Eliminar llamadas a métodos
× ...
@jlrv | @rafaelvindel | @MalagaJUG
Por ejemplo...
@jlrv | @rafaelvindel | @MalagaJUG
Un poquito de historia...
Primera propuesta realizada por Richard Jay Lipton en 1971 cuando era estudiante:
“Fault Diagnosis of Computer Programs”
Un poquito de historia...
No fue hasta 1978 cuando DeMillo, Lipton y Sayward publican:
“Hints on Test Data Selection:
Help for the Practicing Programmer”
En 1980, Timothy Budd publica en su doctorado el primer sistema de mutación:
“Mutation Analysis”
Un poquito de historia...
¿Por qué No tuvo éxito?× Incapacidad para añadir pruebas unitarias en el
desarrollo.
× Dificultades tecnológicas para automatizar las
pruebas.
× Mutaciones muy costosas computacionalmente.
@jlrv | @rafaelvindel | @MalagaJUG
Implementaciones
Mutant Humbug
Mutator
Stryker
Mutator
Grunt Mutation Testing
Nester
Visual Mutator
Ninja Turtles
MuCheck
@jlrv | @rafaelvindel | @MalagaJUG
Implementaciones
PIT
Jester
MuJava
Javalanche
Major
Jumble
Mutator
Judy
@jlrv | @rafaelvindel | @MalagaJUG
IntegracionesCommand Line Maven Gradle IDE SonarQube Concurrency
Javalanche
Jester
PIT
MuJava/MuClipse
Jumble
Mutator
Judy
Major
@jlrv | @rafaelvindel | @MalagaJUG
PITJava Mutation System
PIT
Herramienta que permite realizar pruebas de mutación de forma automática sobre pruebas en Java.
× Rápido× Fácil de usar× En continuo desarrollo
@jlrv | @rafaelvindel | @MalagaJUG
¿Cómo funciona?PIT cambia el bytecode para introducir las mutaciones.
× Números de línea× Nombre del fichero
Para cada mutación, PIT genera una clase Java.
@jlrv | @rafaelvindel | @MalagaJUG
× Killed× Lived× No Coverage× Non Viable× Timeout× Memory Error× Run Error
resultados
@jlrv | @rafaelvindel | @MalagaJUG
condicionales× CONDITIONALS_BOUNDARY: cambia los límites de
las condiciones.
× NEGATE_CONDITIONALS: invierte la lógica de todas las condiciones.
@jlrv | @rafaelvindel | @MalagaJUG
× REMOVE_CONDITIONALS: elimina todas las condiciones.
× REMOVE_CONDITIONALS_EQ_IF× REMOVE_CONDITIONALS_EQ_ELSE× REMOVE_CONDITIONALS_ORD_IF× REMOVE_CONDITIONALS_ORD_ELSE
condicionales
@jlrv | @rafaelvindel | @MalagaJUG
aritméticas× MATH: cambia las operaciones aritméticas por su
inversa.+ -
* /
& |
<< >>
% *
^ *
>>> <<
@jlrv | @rafaelvindel | @MalagaJUG
aritméticas× INCREMENTS: intercambia las operaciones de
incremento y decremento.
× INVERT_NEGS: invierte el signo de los números.
@jlrv | @rafaelvindel | @MalagaJUG
otras
× INLINE_CONSTS: cambiar el valor de las asociaciones de las variables.
boolean true por false y viceversa
int byte short 1 por 0, -1 por 1, 5 por -1 y el resto x + 1
long 1 por 0 y el resto x + 1
float 1.0 y 2.0 por 0.0 y el resto por 1.0
double 1.0 por 0.0 y el resto por 1.0
@jlrv | @rafaelvindel | @MalagaJUG
otras
× RETURN_VALS: cambia el valor devuelto por los métodos.
boolean true por false y viceversa
int byte short 0 por 1 y el resto por 0
long x 1
float double NAN por 0 y el resto - (x + 1.0)
Object not null por null y RuntimeException por null
@jlrv | @rafaelvindel | @MalagaJUG
otras
× VOID_METHOD_CALLS: elimina las invocaciones a todos los métodos que no tengan valor de retorno.
@jlrv | @rafaelvindel | @MalagaJUG
otras
× NON_VOID_METHOD_CALLS: reemplaza el valor de los métodos por sus valores por defecto.
boolean false
int byte short long 0
float double 0.0
char ‘\u0000’
Object null
@jlrv | @rafaelvindel | @MalagaJUG
otras
× CONSTRUCTOR_CALLS: reemplaza el valor devuelto por los constructores por null.
× EXPERIMENTAL_MEMBER_VARIABLE: reemplaza la inicialización de las variables por sus valores por defecto.
@jlrv | @rafaelvindel | @MalagaJUG
otras
× EXPERIMENTAL_SWITCH: cambia el valor devuelto por el switch en función de cada uno de los case.
@jlrv | @rafaelvindel | @MalagaJUG
Activadas Desactivadas
CONDITIONALS_BOUNDARYNEGATE_CONDITIONALS
MATHINCREMENTS
INVERT_NEGSRETURN VALS
VOID_METHOD_CALLS
REMOVE_CONDITIONALSINLINE_CONSTS
NON_VOID_METHOD_CALLSCONSTRUCTOR_CALLS
EXPERIMENTAL_SWITCH
RESUMEN
@jlrv | @rafaelvindel | @MalagaJUG
intellij
@jlrv | @rafaelvindel | @MalagaJUG
maven<build> <plugins> <plugin> <groupId>org.pitest</groupId> <artifactId>pitest-maven</artifactId> <version>1.2.0</version> </plugin> </plugins></build>
mvn org.pitest:pitest-maven:mutationCoverage
mvn org.pitest:pitest-maven:scmMutationCoverage
@jlrv | @rafaelvindel | @MalagaJUG
propiedades× reportsDirectory× outputFormat× targetClasses× targetTests× threads× mutators× mutationThreshold× avoidCallsTo× verbose
@jlrv | @rafaelvindel | @MalagaJUG
Sonar
@jlrv | @rafaelvindel | @MalagaJUG
Place your screenshot here{Let’s Code!}
Análisis Incremental× Si se detecta un bucle infinito y no se cambia la
clase, se sigue asumiendo el bucle infinito.
× Si se elimina una mutación y no se cambia la clase ni la prueba, se sigue asumiendo que se elimina.
@jlrv | @rafaelvindel | @MalagaJUG
Análisis Incremental× Si una mutación sobrevive y no se cambia la
clase ni su cobertura, se sigue asumiendo que sobrevive.
@jlrv | @rafaelvindel | @MalagaJUG
Análisis Incremental× withHistory: para activarlo o desactivarlo.× historyInputFile: fichero de donde leer el análisis
anterior.× historyOutputFile: fichero donde escribir el
resultado del análisis actual (puede ser igual al anterior).
@jlrv | @rafaelvindel | @MalagaJUG
mutation result listener× Recibe los resultados de las pruebas y se
configura en outputFormats.
× Para añadirlo, implementar:
org.pitest.mutationtest.MutationResultListenerFactory
@jlrv | @rafaelvindel | @MalagaJUG
mutation filter× Se pueden eliminar las mutaciones generadas
antes de ser ejecutadas sobre las pruebas.
× Para añadirlo, implementar:
org.pitest.mutationtest.filter.MutationFilterFactory
@jlrv | @rafaelvindel | @MalagaJUG
test prioritiser× Se puede personalizar el orden de ejecución de
las pruebas contra las mutaciones.
× Para añadirlo, implementar:
org.pitest.mutationtest.build.TestPrioritiserFactory
@jlrv | @rafaelvindel | @MalagaJUG
mutation engine× Se puede proporcionar un motor de mutación
personalizado indicado por mutationEngine.
× Para más información, consultar:
org.pitest.mutationtest.engine.gregor.*
@jlrv | @rafaelvindel | @MalagaJUG
Conclusiones
Ventajas
× Ayuda a mejorar la calidad de las pruebas.
× Ayuda a detectar errores de forma y contenido en las pruebas.
@jlrv | @rafaelvindel | @MalagaJUG
inconvenientes× Elevado tiempo de ejecución:
× Volumen de código a ser analizado.× Conjunto de mutaciones a realizar.× La cantidad de test que haya que ejecutar.
× Los resultados deben ser correctamente interpretados:
× Falsos positivos.
@jlrv | @rafaelvindel | @MalagaJUG
Ejemplos de tiempos de ejecución
@jlrv | @rafaelvindel | @MalagaJUG
frente a los altos tiempos de Ejecución...
× Acotar el conjunto de clases mutadas.
× Acotar el conjunto de pruebas ejecutados.
× Análisis incrementales.
@jlrv | @rafaelvindel | @MalagaJUG
frente a los Falsos positivos...
× Puede desenmascarar pruebas ambiguas por lo
que mejora también la calidad de las pruebas.
@jlrv | @rafaelvindel | @MalagaJUG
Resumiendo...× ¿Es la cobertura una medida real de calidad?
× Altamente falsificada, no representa un valor real.
@jlrv | @rafaelvindel | @MalagaJUG
Resumiendo...× ¿Ha sido probado a fondo? ¿Son pruebas
adecuadas? ¿Son pruebas de calidad?
× Puede que sí o puede que no, pero ahora lo sabemos.
@jlrv | @rafaelvindel | @MalagaJUG
¡gracias!
Be One Of Us
[email protected]● Horario flexible● Aprendizaje continuo● Equipo joven y proactivo● Herramientas de última generación● ...
Who watches the watchmen?
Enlaces de Interés y Referencias Utilizadas (I)× https://disciplinas.stoa.usp.br/pluginfile.php/1943431/mod_resou
rce/content/1/Hints_on_Test_Data_Selection-Demillo.pdf× https://www.computer.org/csdl/mags/co/1978/04/01646911.pdf× http://cpsc.yale.edu/sites/default/files/files/tr155.pdf× https://stryker-mutator.github.io/× http://jester.sourceforge.net/× http://jumble.sourceforge.net/× http://pitest.org/
@jlrv | @rafaelvindel | @MalagaJUG
Enlaces de Interés y Referencias Utilizadas (II)× http://javalanche.org/× https://github.com/david-schuler/javalanche× https://cs.gmu.edu/~offutt/mujava/× http://www.mutationtesting.org/× http://mutation-testing.org/× https://github.com/mbj/mutant× https://github.com/padraic/humbug× http://ortask.com/mutator/
@jlrv | @rafaelvindel | @MalagaJUG
Enlaces de Interés y Referencias Utilizadas (III)× https://github.com/stryker-mutator/stryker× https://www.npmjs.com/package/grunt-mutation-testing× http://nester.sourceforge.net/× https://visualmutator.github.io/web/× https://ninjaturtles.codeplex.com/× https://hackage.haskell.org/package/MuCheck
@jlrv | @rafaelvindel | @MalagaJUG