¿En qué la estamos regando en pruebas de software?
Agustín Ramos @MachinesAreUs
¿Cuántas pruebas necesita ésta función?
function partition(items, left, right) { var pivot = items[Math.floor((right + left) / 2)], i = left, j = right; while (i <= j) { while (items[i] < pivot) { i++; } while (items[j] > pivot) { j—; } if (i <= j) { swap(items, i, j); i++; j--; } } return i; }
function partition(items, left, right) { var pivot = items[Math.floor((right + left) / 2)], i = left, j = right; while (i <= j) { while (items[i] < pivot) { i++; } while (items[j] > pivot) { j—; } if (i <= j) { swap(items, i, j); i++; j--; } } return i; }
¿Cuántos tipos de pruebas necesita esta función?
¿Cuántos tipos de pruebas necesita esta función?
Valores en rangos esperados
Condiciones de frontera.
Valores no esperados (e.g. nulos)
Combinaciones de los anteriores
Valores que ejerciten las distintas rutas.
¿Cuántas rutas de ejecución tiene este programa?
function partition(items, left, right) { var pivot = items[Math.floor((right + left) / 2)], i = left, j = right; while (i <= j) { while (items[i] < pivot) { i++; } while (items[j] > pivot) { j—; } if (i <= j) { swap(items, i, j); i++; j--; } } return i; }
Complejidad CiclomáticaMétrica.
Thomas J. McCabe, 1976
Mide el número de rutas de ejecución linealmente independientes dentro de un programa.
Formalmente M = E − N + 2P
Aproximador: 2^N - 1 donde N es el número de bifurcaciones en el código (bloques if, where, for, etc.)
Entonces… ¿Cuándo vas a acabar de probar?
Para empezar… ¿Cómo sabes que has probado lo
suficiente?
¿Cobertura?
Cobertura“Tenemos cobertura a nivel de código superior al 90%,
lo cual es indicador de nuestro alto nivel de calidad”
¿Cobertura?
Una línea de código que está “cubierta” (se ha ejecutado durante una prueba) no me dice nada del contexto en el cual se ejecutó (e.g. los parámetros de entrada de la función, el número de iteración si se encuentra dentro de un bloque, etc), y por lo tanto
no me dice que no puede fallar o tener un comportamiento distinto en un contexto distinto.
¡A trabajar!
Data Driven Testing (DDT)
Data Driven Testing
Same test
Many input/output pairs.
Test
DDT en CucumberFeature: Addition I want to be told the sum of two numbers ! Scenario Outline: Add two numbers Given I have entered <input_1> into the calculator And I have entered <input_2> into the calculator When I press <button> Then the result should be <output> on the screen ! Examples: | input_1 | input_2 | button | output | | 20 | 30 | add | 50 | | 2 | 5 | add | 7 | | 0 | 40 | add | 40 |
DDT en Spock
class HelloSpock extends spock.lang.Specification { def "length of Spock's and his friends' names"() { expect: name.size() == length ! where: name | length "Spock" | 5 "Kirk" | 4 "Scotty" | 6 } }
¿De dónde salen los casos?
A mano.
En general, no acabas.
¿Cómo sabes que son suficientes?
¡Son solo los que se te ocurren!
Generación automatizada.
Random.
¿Cómo sabes que son suficientes?
Todas las posibles combinaciones de entradas/condiciones…
¿Cuál es el P.E.X?
Explosión combinatorial
N-wise testing
Pairwise testing
“Pairwise (a.k.a. all-pairs) testing is an effective test case generation technique that is based on the observation that most faults are caused by interactions of at
most two factors. Pairwise-generated test suites cover all combinations of two therefore are much smaller than
exhaustive ones yet still very effective in finding defects.”
http://www.pairwise.org/
most ~ > 90 %
Pairwise Testing
Pairwise Testing In The Real World
Pruebas Basadas en Riesgos
Pruebas Basadas en Riesgos
Dados recursos finitos ¿cómo escoger qué probar más y qué menos?
Estrategia:
Objetivo: Encontrar los defectos más importantes tan pronto como sea posible y con el menor costo.
No hay riesgo => No hay pruebas.
Decisión de negocio
¿Qué es el Riesgo?
!
Pruebas Basadas en Riesgos
La fórmula
R(f) = P(f) * C(f)
R(f) - Riesgo calculado de la función f
P(f) - Probabilidad de falla de la función f
C(f) - Costo de falla de la función f
Análisis de Riesgos + Pruebas
!
Pruebas Basadas en Riesgos
Formulación original (James Bach):
http://www.satisfice.com/articles/hrbt.pdf
Presentación (con más tips):
http://www.cs.tut.fi/tapahtumat/testaus04/schaefer.pdf
Property-Based Testing
Property-Based Testing
Si tenemos una función
reverse :: String -> String
Entonces una propiedad puede definirse como:
reverse (reverse xs) == xs
Y podemos permitir que herramientas como QuickCheck generen “aleatoriamente" ejemplos de xs y verifiquen que estos ejemplos cumplan con la propiedad
Property Based … +
PairWise Testing?
Complexity Brings More Complexity
… and “More is Different”Phillip Anderson
Science, Vol. 177, No. 4047, 1972
Test me M@#3rfvkc3R
Test this M@+3rfükC3r !
Architecture Testing
Testing /= Checking !
http://www.developsense.com/blog/2009/08/testing-vs-checking/
Test Data Generation !
https://gist.github.com/MachinesAreUs/d236e9ca726dd554dad0