quickcheck
play

QuickCheck John Hughes Chalmers University/Quviq AB What is - PowerPoint PPT Presentation

Specification Based Testing with QuickCheck John Hughes Chalmers University/Quviq AB What is QuickCheck? A library for writing and testing properties of program code Some code: A property: Properties as Code A test data A


  1. Specification Based Testing with QuickCheck John Hughes Chalmers University/Quviq AB

  2. What is QuickCheck? • A library for writing and testing properties of program code • Some code: • A property:

  3. Properties as Code A test data A quantifier! A macro! generator! A set! An ordinary A boolean- function valued definition! A predicate! expression!

  4. DEMO

  5. QuickCheck in a Nutshell Test case Test case Test case Properties Test case Test case Minimal Test case

  6. QuickCheck Properties: things with a counterexample <bool-exp> ?FORALL (<var>,<generator>,<property>) ?IMPLIES (<bool-exp>,<property>) conjunction, disjunction ?EXISTS (<var>,<generator>,<property>)

  7. QuickCheck Generators int(), bool (), real()… choose(<int>,<int>) { <generator> , <generator >… } oneof (<list-of-generators>) ?LET (<var>,<generator>,<generator>)

  8. Example: Sorted Lists sorted_list_int() -> ?LET(L,list(int()), sort(L)).

  9. Benefits • Less time spent writing test code – One property replaces many tests • Better testing – Lots of combinations you’d never test by hand • Less time spent on diagnosis – Failures minimized automagically

  10. An Experiment Unit Properties tests

  11. How good were the tests at finding bugs — in other students’ code? 6 5 4 Hunit Unit tests 3 QuickCheck 2 1 0 0 1 2 3 4 5 6 7 8 9 10 11 1 2 3 4 5 6 7 8 9 10 11 12 Better

  12. Tests for Base 64 encoding Expected results base64_encode(Config) when is_list(Config) -> %% Two pads <<"QWxhZGRpbjpvcGVuIHNlc2FtZQ==">> = Test cases base64:encode("Aladdin:open sesame"), %% One pad <<"SGVsbG8gV29ybGQ=">> = base64:encode(<<"Hello World">>), %% No pad "QWxhZGRpbjpvcGVuIHNlc2Ft" = base64:encode_to_string("Aladdin:open sesam"), "MDEyMzQ1Njc4OSFAIzBeJiooKTs6PD4sLiBbXXt9" = base64:encode_to_string( <<"0123456789!@#0^&*();:<>,. []{}">>), ok.

  13. Writing a Property prop_base64() -> ?FORALL(Data,list(choose(0,255)), base64:encode(Data) == ??? ).

  14. Round-trip Properties prop_encode_decode() -> ?FORALL(L,list(choose(0,255)), base64:decode(base64:encode(L)) == list_to_binary(L)). -define(DECODE_MAP, -define(DECODE_MAP, {bad,bad,bad,bad,bad,bad,bad,bad,ws,ws,bad,bad,ws,bad,bad, {bad,bad,bad,bad,bad,bad,bad,bad,ws,ws,bad,bad,ws,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, ws,bad,bad,bad,bad,bad,bad,bad,bad,bad,62,bad,bad,bad,bad,63, ws,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,62,bad,bad,bad,63, 52,53,54,55,56,57,58,59,60,61,bad,bad,bad,eq,bad,bad, 52,53,54,55,56,57,58,59,60,61,bad,bad,bad,eq,bad,bad, bad,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14, bad,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14, 15,16,17,18,19,20,21,22,23,24,25,bad,bad,bad,bad,bad, 15,16,17,18,19,20,21,22,23,24,25,bad,bad,bad,bad,bad, NOT caught by the bad,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, bad,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40, test suite 41,42,43,44,45,46,47,48,49,50,51,bad,bad,bad,bad,bad, 41,42,43,44,45,46,47,48,49,50,51,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad, bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,bad,

  15. Round-trip Properties prop_encode_decode() -> ?FORALL(L,list(choose(0,255)), base64:decode(base64:encode(L)) == list_to_binary(L)). 117> eqc:quickcheck(base64_eqc:prop_encode_decode()). ...................................Failed! Reason: {'EXIT',{badarg,43}} After 36 tests. [204,15,130] Shrinking...(3 times) The table entry we Reason: {'EXIT',{badarg,43}} changed [0,0,62]

  16. Round-trip Properties prop_encode_decode() -> ?FORALL(L,list(choose(0,255)), base64:decode(base64:encode(L)) == list_to_binary(L)). What does this test? • NOT a complete test — will not find a consistent misunderstanding of base64 • WILL find mistakes in encoder or decoder Simple properties find a lot of bugs!

  17. Back to the tests… Where did base64_encode(Config) when is_list(Config) -> these come %% Two pads from? <<"QWxhZGRpbjpvcGVuIHNlc2FtZQ==">> = base64:encode("Aladdin:open sesame"), %% One pad <<"SGVsbG8gV29ybGQ=">> = base64:encode(<<"Hello World">>), %% No pad "QWxhZGRpbjpvcGVuIHNlc2Ft" = base64:encode_to_string("Aladdin:open sesam"), "MDEyMzQ1Njc4OSFAIzBeJiooKTs6PD4sLiBbXXt9" = base64:encode_to_string( <<"0123456789!@#0^&*();:<>,. []{}">>), ok.

  18. Possibilities Use the other • Someone converted the data by hand encoder as an oracle • Another base64 encoder Use an old version (or a • The same base64 encoder! simpler version) – Only tests that changes don’t affect the result, not as an oracle that the result is right

  19. Commuting Diagram Properties

  20. Property Types in Class Examples • Rex Page: 71 properties in University of Oklahoma courses in Software Engineering, Applied Logic (QuickCheck+ACL2) Round trip Commuting diagram Other

  21. Time for some C code …

  22. Testing Stateful Code API API API API Calls Calls Calls Calls postconditions Model Model Model Model state state state state A list of numbers!

  23. A QuickCheck Property prop_q() -> ?FORALL(Cmds,commands(?MODULE), begin {H,S,Res} = run_commands(?MODULE,Cmds), Res == ok) end).

  24. Let’s run some tests…

  25. Exercises  Practice  Small scale Large scale  Property-driven Testing legacy development code  Trivial inputs Complex inputs

  26. Example: Ericsson Media Proxy Many, many Megaco Megaco Megaco Megaco Lots of work parameters, can response response request request to write be 1 — 2 pages generators per message! State machine models fit the problem well

  27. Ericsson Media Proxy Bug • Test adding and removing callers from a call Add Add Sub Add Sub Add Sub Call Full

  28. • Relational databases don’t scale to ”Big Data” A highly scalable, • ” noSQL ” databases are a popular alternative reliable, available and low-latency distributed key- value store

  29. Put and Get put 0 get 0 put 1 get 1

  30. Conflicts QuickCheck model: record each client’s current view of the data; put put replaces that view 0 put 1 get {0,1} put 2 get 2

  31. Example QuickCheck model: client’s view is fresh or stale : updating a stale view put just adds to the conflicts … 0 put 1 get {0,1} put 2 put 3 get get {0,1,2,3} ??? A vector clock optimisation …

  32. Example put 0 get get get ?? 0 {0,0}

  33. Duplicate value explained 0 12:43:27 put 0 0 12:43:27 get get 0 {0,0} 0 12:43:27 12:43:28

  34. Eventual Consistency • ”For any sequence of operations, with any node or network failures, Riak eventually reaches a consistent state ” – When is ” eventually ”? • For any sequence of operations sent to any subsets of server nodes (because of failures), completing all Riak’s repair operations results in a consistent state.

  35. AutoSAR • Joint project with Quviq, SP, Volvo Cars, Mentor Graphics…

  36. AutoSAR Basic Software

  37. The Story So Far… • QuickCheck state-machine models for 3 AutoSAR clusters (Com/PDUR, CAN, FlexRay) • Used to test software from 3 suppliers • Bugs revealed in all! – Plus reinterpretations of the standard

  38. uint32

  39. COM Component • 500 pages of standard • 250 pages of C • 25 pages of QuickCheck

  40. "We know there is a lurking bug somewhere in the dets code. We have got 'bad object' and 'premature eof' every other month the last year. We have not been able to track the bug down since the dets files is repaired automatically next time it is opened.“ Tobbe Törnqvist, Klarna, 2007

  41. >500 What is it? people in 5 years Application Invoicing services for web shops Distributed database: Mnesia transactions, distribution, replication Dets Tuple storage Race File system conditions?

  42. Imagine Testing This… dispenser:take_ticket() dispenser:reset()

  43. A Unit Test in Erlang test_dispenser() -> ok = reset(), 1 = take_ticket(), 2 = take_ticket(), 3 = take_ticket(), ok = reset(), 1 = take_ticket(). Expected BUT… results

  44. A Parallel Unit Test ok reset 1 1 1 take_ticket 3 2 1 take_ticket take_ticket 2 3 2 • Three possible correct outcomes!

  45. Another Parallel Test A killer app for reset properties! take_ticket take_ticket reset take_ticket take_ticket • 42 possible correct outcomes!

  46. Modelling the dispenser take take take reset ok 1 2 3 0 0 1 2

Recommend


More recommend