property based testing usando quickcheck
TRANSCRIPT
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
“Program testing can be used to show the presence of bugs, but never to show
their absence”
Edsger Dijkstra
@Test public void testUnity() { assertEquals(1, f1(1)); }
100% code coverage!
double f1(int x) { return 1/x; }
Joe Armstrong (Erlang)
Átomos en la tierra: 1.33 x 10^50
2^k=10^50k=50log(10)/log(2)k=166.09k/32=5.18
https://www.youtube.com/watch?v=lKXe3HUG2l4
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.
Fred Brooks
No Silver Bullet Essence and Accidents of Software Engineering
Definir propiedades que tiene que cumplir nuestro sistema
para cierto dominio de valores.
Property based testing
0 1 1 0 2 -4 0 5 -7 -8 4 5 3 11 -9 -4 6 -5 -3 0
[] [] [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]
Enteros int
Vectores de enteros [int]
() () (false) (false true false) (false true) (false true true true) (true) (false false true true) () (true)
Listas de booleanos (bool)
{:user-name "kWodcsE2", :user-id 1, :email "[email protected]", :active? true}
Estructuras compuestas“hZO*3" “m-W2@KL” ",P+po0#2 “ "tlt^[ ui`V"
Alfanuméricos (string)
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]);
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.
Cómo se define una propiedad?
Promueve una visión de más alto nivel con restricciones que se deben satisfacer de manera
universal.
Ejemplo:
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()]]) ]);
(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
Clojure
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()]]) ]);
(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
Clojure
Un nombre para la propiedad…
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()]]) ]);
(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
Clojure
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()]]) ]);
(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
Clojure
Invocar a la función para elvalor 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()]]) ]);
(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
Clojure
Validar que la propiedadse 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()]]) ]);
(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
Clojure
Ejecutar 10 casos…
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()]]) ]);
(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
Clojure
=> {:result false, :failing-size 0, :num-tests 1, :fail [[3]], :shrunk {:total-nodes-visited 5, :depth 2, :result false, :smallest [[0]]}}
(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]]}}
(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))))
http://www.slideshare.net/PhilipKoopman/toyota-unintended-acceleration
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