Download Descargar

Document related concepts
no text concepts found
Transcript
Property Based
Testing
(También conocido como Generative Testing)
@guilespi
Guillermo Winkler
Guillermo Winkler
Ingeniero
Guillermo Winkler
Ingeniero
Programador
Guillermo Winkler
Ingeniero
Programador
Tester
Property Based
Testing
O Cómo no escribir mas Unit Tests
Property Based
Testing
O Cómo no escribir mas Unit Tests
Types vs. Tests
Cuál es la mejor forma de
demostrar que nuestros
sistemas son correctos?
(O sea que hacen lo que tienen que hacer)
Cuál es la mejor forma de
demostrar que nuestros
sistemas son correctos?
(O sea que hacen lo que tienen que hacer)
Types
•
Sirven como parte de la especificación
•
Ayudan durante el diseño
•
Ayudan a capturar requerimientos
Tests
•
Sirven como parte de la especificación
•
Sirven como “comentarios ejecutables”
•
Ayudan durante el diseño
•
Ayudan a capturar requerimientos
Una lista de timestamps en
Scala
Un loop en Ruby
“Program testing can be used to show
the presence of bugs, but never to show
their absence”
Edsger Dijkstra
double f1(int x) {
return 1/x;
}
@Test
public void testUnity() {
assertEquals(1, f1(1));
}
double f1(int x) {
return 1/x;
}
@Test
public void testUnity() {
assertEquals(1, f1(1));
}
100% code
coverage!
Patch
Quién se morfo el unit test?
Átomos en la tierra:
1.33 x 10^50
Joe Armstrong
(Erlang)
https://www.youtube.com/watch?v=lKXe3HUG2l4
2^k=10^50
k=50log(10)/log(2)
k=166.09
k/32=5.18
Un programa en C con 6 enteros
tiene más estados posibles que
átomos hay en el planeta…
Un programa en C con 6 enteros
tiene más estados posibles que
átomos hay en el planeta…
?
Fred Brooks
Digital computers are more complex than most things that
people build. They have large numbers of states. Software
systems have orders of magnitude more states than
computers do.
No Silver Bullet
Essence and Accidents of Software Engineering
Property based testing
Definir propiedades que tiene
que cumplir nuestro sistema
para cierto dominio de valores.
Property based testing
Poner al sistema en la
mayor cantidad de
estados posibles
Precisamos generar valores
(De ahí lo de generative testing)
Enteros int
0 1 1 0 2 -4 0 5 -7 -8 4 5 3 11 -9 -4 6 -5 -3 0
Vectores de enteros [int]
[] [] [1] [1] [] [] [5 6 6 2 0 1] [3 7 5] [2 0 0 6 2 5 8] [9 1 9 3 8 3 5]
Listas de booleanos (bool)
() () (false) (false true false) (false true) (false true true true) (true)
(false false true true) () (true)
Alfanuméricos (string)
“hZO*3" “m-W2@KL” ",P+po0#2 “ "tlt^[ ui`V"
Estructuras compuestas
{:user-name "kWodcsE2",
:user-id 1,
:email "[email protected]",
:active? true}
QuickCheck
•
•
•
•
•
•
•
•
•
•
•
•
•
C
C++
Chicken Scheme
Clojure
Common Lisp
D
Elm
Erlang
F#
Factor
Io
Java
Javascript
•
•
•
•
•
•
•
•
•
•
•
•
Node.js
Objective-C
OCaml
Perl
Prolog
Python
R
Ruby
Scala
Scheme
Smalltalk
Standard ML
function sort(values) {
var length = values.length - 1;
do {
var swapped = false;
for(var i = 0; i < length; ++i) {
if (values[i] > values[i+1]) {
var temp = values[i];
values[i] = values[i+1];
values[i+1] = temp;
swapped = true;
}
}
}
while(swapped == true)
};
sort([7, 4, 5, 2, 9, 1]);
Cómo se define una
propiedad?
Ejemplo:
En un array ordenado el primer elemento
es siempre menor que el último.
Cómo se define una
propiedad?
Ejemplo:
En un array ordenado el primer elemento
es siempre menor que el último.
Promueve una visión de más alto nivel con
restricciones que se deben satisfacer de manera
universal.
Javascript
JSC.reps(10);
JSC.test(
"First is lower than last after sort",
function (verdict, v) {
var sorted = v.sort();
return verdict(sorted[0] < sorted[sorted.length - 1]);
},
[
JSC.array([JSC.integer()]])
]
);
Clojure
(def prop-sorted-first-less-than-last
(prop/for-all [v (gen/vector gen/int)]
(let [s (sort v)]
(< (first s) (last s)))))
(tc/quick-check 10 prop-sorted-first-less-than-last)
Un nombre para la propiedad…
Javascript
JSC.reps(10);
JSC.test(
"First is lower than last after sort",
function (verdict, v) {
var sorted = v.sort();
return verdict(sorted[0] < sorted[sorted.length - 1]);
},
[
JSC.array([JSC.integer()]])
]
);
Clojure
(def prop-sorted-first-less-than-last
(prop/for-all [v (gen/vector gen/int)]
(let [s (sort v)]
(< (first s) (last s)))))
(tc/quick-check 10 prop-sorted-first-less-than-last)
Javascript
Un generador de valores
para la función a testear…
JSC.reps(10);
JSC.test(
"First is lower than last after sort",
function (verdict, v) {
var sorted = v.sort();
return verdict(sorted[0] < sorted[sorted.length - 1]);
},
[
JSC.array([JSC.integer()]])
]
);
Clojure
(def prop-sorted-first-less-than-last
(prop/for-all [v (gen/vector gen/int)]
(let [s (sort v)]
(< (first s) (last s)))))
(tc/quick-check 10 prop-sorted-first-less-than-last)
Javascript
Invocar a la función para el
valor generado…
JSC.reps(10);
JSC.test(
"First is lower than last after sort",
function (verdict, v) {
var sorted = v.sort();
return verdict(sorted[0] < sorted[sorted.length - 1]);
},
[
JSC.array([JSC.integer()]])
]
);
Clojure
(def prop-sorted-first-less-than-last
(prop/for-all [v (gen/vector gen/int)]
(let [s (sort v)]
(< (first s) (last s)))))
(tc/quick-check 10 prop-sorted-first-less-than-last)
Javascript
Validar que la propiedad
se cumple…
JSC.reps(10);
JSC.test(
"First is lower than last after sort",
function (verdict, v) {
var sorted = v.sort();
return verdict(sorted[0] < sorted[sorted.length - 1]);
},
[
JSC.array([JSC.integer()]])
]
);
Clojure
(def prop-sorted-first-less-than-last
(prop/for-all [v (gen/vector gen/int)]
(let [s (sort v)]
(< (first s) (last s)))))
(tc/quick-check 10 prop-sorted-first-less-than-last)
Ejecutar 10 casos…
Javascript
JSC.reps(10);
JSC.test(
"First is lower than last after sort",
function (verdict, v) {
var sorted = v.sort();
return verdict(sorted[0] < sorted[sorted.length - 1]);
},
[
JSC.array([JSC.integer()]])
]
);
Clojure
(def prop-sorted-first-less-than-last
(prop/for-all [v (gen/vector gen/int)]
(let [s (sort v)]
(< (first s) (last s)))))
(tc/quick-check 10 prop-sorted-first-less-than-last)
Javascript
JSC.reps(10);
JSC.test(
"First is lower than last after sort",
function (verdict, v) {
var sorted = v.sort();
return verdict(sorted[0] < sorted[sorted.length - 1]);
},
[
JSC.array([JSC.integer()]])
]
);
Clojure
(def prop-sorted-first-less-than-last
(prop/for-all [v (gen/vector gen/int)]
(let [s (sort v)]
(< (first s) (last s)))))
(tc/quick-check 10 prop-sorted-first-less-than-last)
=> {:result false,
:failing-size 0,
:num-tests 1,
:fail [[3]],
:shrunk {:total-nodes-visited 5,
:depth 2,
:result false,
:smallest [[0]]}}
Shrinking
(def prop-no-42
(prop/for-all [v (gen/vector gen/int)]
(not (some #{42} v))))
(tc/quick-check 100 prop-no-42)
;; => {:result false,
:failing-size 45,
:num-tests 46,
:fail [[10 1 28 40 11 -33 42 -42 39 -13 13
-44 -36 11 27 -42 4 21 -39]],
:shrunk {:total-nodes-visited 38,
:depth 18,
:result false,
:smallest [[42]]}}
(def prop-no-42
(prop/for-all [v (gen/vector gen/int)]
(not (some #{42} v))))
(tc/quick-check 100 prop-no-42)
;; => {:result false,
:failing-size 45,
:num-tests 46,
:fail [[10 1 28 40 11 -33 42 -42 39 -13 13
-44 -36 11 27 -42 4 21 -39]],
:shrunk {:total-nodes-visited 38,
:depth 18,
:result false,
:smallest [[42]]}}
(def prop-no-42
(prop/for-all [v (gen/vector gen/int)]
(not (some #{42} v))))
(tc/quick-check 100 prop-no-42)
;; => {:result false,
:failing-size 45,
:num-tests 46,
:fail [[10 1 28 40 11 -33 42 -42 39 -13 13
-44 -36 11 27 -42 4 21 -39]],
:shrunk {:total-nodes-visited 38,
:depth 18,
:result false,
:smallest [[42]]}}
Shrink Tree
http://www.slideshare.net/PhilipKoopman/toyota-unintended-acceleration
http://www.quviq.com/volvo-quickcheck/
Property Based Testing
•
Es complementario con unit tests y/o type systems.
•
Promueve una visión de más alto nivel sobre las
definiciones en nuestras pruebas.
•
Permite poner a nuestro sistema en una cantidad de
estados solo alcanzable de forma computacional.
•
Antes que los errores ocurran para prevenir
•
Después que ocurran para diagnosticar