be er tes ng with less work quickcheck tes ng in prac ce
play

Be#er Tes(ng with Less Work: QuickCheck Tes(ng in Prac(ce - PowerPoint PPT Presentation

Be#er Tes(ng with Less Work: QuickCheck Tes(ng in Prac(ce John Hughes QuickCheck in a Nutshell Test case Test case Test case Proper(es Test


  1. Be#er ¡Tes(ng ¡with ¡Less ¡Work: ¡ QuickCheck ¡Tes(ng ¡in ¡Prac(ce ¡ John ¡Hughes ¡

  2. QuickCheck ¡in ¡a ¡Nutshell ¡ Test ¡case ¡ Test ¡case ¡ Test ¡case ¡ Proper(es ¡ Test ¡case ¡ Test ¡case ¡ Minimal Test ¡case ¡

  3. Benefits ¡ • Less ¡(me ¡spent ¡wri(ng ¡test ¡code ¡ – One ¡property ¡replaces ¡many ¡tests ¡ • Be#er ¡tes(ng ¡ – Lots ¡of ¡combina(ons ¡you’d ¡never ¡test ¡by ¡hand ¡ • Less ¡(me ¡spent ¡on ¡diagnosis ¡ – Failures ¡minimized ¡automagically ¡

  4. 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.

  5. Wri(ng ¡a ¡Property ¡ prop_base64() -> ?FORALL(Data,list(choose(0,255)), base64:encode(Data)== ??? ).

  6. Back ¡to ¡the ¡tests… ¡ Where ¡did ¡ these ¡come ¡ base64_encode(Config) when is_list(Config) -> %% 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.

  7. Possibili(es ¡ 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 ¡

  8. Round-­‑trip ¡Proper(es ¡ 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 ¡proper6es ¡find ¡a ¡lot ¡of ¡bugs! ¡

  9. Lessons ¡ • Coming ¡up ¡with ¡proper(es ¡can ¡require ¡a ¡li#le ¡ ingenuity… ¡ • …but ¡simple ¡proper(es ¡are ¡surprisingly ¡ effec(ve! ¡ • Comparing ¡two ¡ways ¡to ¡compute ¡the ¡same ¡ thing ¡is ¡ o"en ¡powerful! ¡

  10. Time ¡to ¡test ¡some ¡C ¡code… ¡

  11. Modelling ¡in ¡Erlang ¡ API ¡ API ¡ API ¡ API ¡ Calls ¡ Calls ¡ Calls ¡ Calls ¡ postcondi6ons ¡ Model ¡ Model ¡ Model ¡ Model ¡ state ¡ state ¡ state ¡ state ¡

  12. Example ¡ Use ¡an ¡Erlang ¡list ¡to ¡model ¡the ¡contents ¡of ¡the ¡queue! ¡ put ¡ put ¡ put ¡ get ¡ get ¡ 1 ¡ 2 ¡ 3 ¡ [] ¡ [1] ¡ [2] ¡ [1,2] ¡ [2,3] ¡ 1 ¡ 2 ¡

  13. Code ¡Fragments ¡ next_state_data(_,_,S,_,{call,_,put,[_,X]}) ¡-­‑> ¡ ¡ ¡ ¡ ¡S#state{elements=S#state.elements++[X]}; ¡ next_state_data(_,_,S,_,{call,_,get,_}) ¡-­‑> ¡ ¡ ¡ ¡ ¡S#state{elements=tl(S#state.elements)}; ¡ postcondi(on(_,_,S,{call,_,get,_},Res) ¡-­‑> ¡ ¡ ¡ ¡ ¡Res ¡== ¡hd(S#state.elements); ¡ postcondi(on(_,_,S,{call,_,size,_},Res) ¡-­‑> ¡ ¡ ¡ ¡ ¡Res ¡== ¡length(S#state.elements); ¡

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

  15. Let’s ¡run ¡some ¡tests… ¡

  16. Lessons ¡ • One ¡property ¡can ¡find ¡ many ¡bugs ¡ • Shrinking ¡makes ¡diagnosis ¡ very ¡simple ¡

  17. AutoSAR ¡ • Joint ¡project ¡with ¡Quviq, ¡SP, ¡Volvo ¡Cars ¡and ¡ Mentor ¡Graphics ¡

  18. AutoSAR ¡Architecture ¡

  19. The ¡Story ¡So ¡Far… ¡ • QuickCheck ¡state-­‑machine ¡models ¡for ¡ AutoSAR ¡clusters ¡ ¡ – Com, ¡PDUR, ¡CAN, ¡FlexRay, ¡Lin, ¡DEM… ¡ • Used ¡to ¡test ¡soqware ¡from ¡3 ¡suppliers ¡ – test ¡code ¡10x ¡smaller ¡than ¡implementa(on ¡ – 20x ¡smaller ¡than ¡the ¡standard! ¡ • Bugs ¡and ¡inconsistencies ¡revealed ¡in ¡all! ¡ – And ¡in ¡the ¡standard… ¡

  20. "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 ¡ automa(cally ¡next ¡(me ¡it ¡is ¡opened.“ ¡ Tobbe ¡Törnqvist, ¡Klarna, ¡2007 ¡

  21. 500+ ¡ What ¡is ¡it? ¡ people ¡in ¡ 5 ¡years ¡ Applica(on ¡ Invoicing ¡services ¡for ¡web ¡shops ¡ Distributed ¡database: ¡ Mnesia ¡ transac(ons, ¡distribu(on, ¡ replica(on ¡ Dets ¡ Tuple ¡storage ¡ Race ¡ File ¡system ¡ condi(ons? ¡

  22. Imagine ¡Tes(ng ¡This… ¡ dispenser:take_(cket() ¡ dispenser:reset() ¡

  23. 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 ¡

  24. A ¡Parallel ¡Unit ¡Test ¡ ok ¡ reset ¡ 1 ¡ 1 ¡ 1 ¡ take_(cket ¡ 3 ¡ 2 ¡ 1 ¡ take_(cket ¡ take_(cket ¡ 2 ¡ 3 ¡ 2 ¡ • Three ¡possible ¡correct ¡ outcomes! ¡

  25. Another ¡Parallel ¡Test ¡ reset ¡ take_(cket ¡ take_(cket ¡ reset ¡ take_(cket ¡ take_(cket ¡ • 42 ¡possible ¡correct ¡outcomes! ¡

  26. Modelling ¡the ¡dispenser ¡ take ¡ take ¡ take ¡ reset ¡ 0 ¡ 0 ¡ 1 ¡ 2 ¡ ok ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡1 ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡2 ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡ ¡3 ¡

  27. Parallel ¡Test ¡Cases ¡ take take  1 ¡  3 ¡ reset  ok ¡ take  2 ¡ 0 ¡ 0 ¡ 1 ¡ 2 ¡

  28. Generate ¡parallel ¡ test ¡cases ¡ prop_parallel() -> ?FORALL(Cmds,parallel_commands(?MODULE), begin start(), {H,Par,Res} = run_parallel_commands(?MODULE,Cmds), Res == ok) end)). Run ¡tests, ¡check ¡for ¡a ¡ matching ¡serializa(on ¡

  29. Let’s ¡run ¡some ¡tests ¡

  30. take_(cket() ¡-­‑> ¡ ¡ ¡ ¡ ¡N ¡= ¡read(), ¡ Prefix: ¡ ¡ ¡ ¡ ¡write(N+1), ¡ ¡ ¡ ¡ ¡N+1. ¡ Parallel: ¡ 1. ¡take_(cket() ¡-­‑-­‑> ¡1 ¡ 2. ¡take_(cket() ¡-­‑-­‑> ¡1 ¡ Result: ¡no_possible_interleaving ¡

  31. dets ¡ • Tuple ¡store: ¡ ¡{Key, ¡Value1, ¡Value2…} ¡ • Opera(ons: ¡ – insert(Table,ListOfTuples) ¡ – delete(Table,Key) ¡ – insert_new(Table,ListOfTuples) ¡ – … ¡ • Model: ¡ – List ¡of ¡tuples ¡(almost) ¡

  32. QuickCheck ¡Specifica(on ¡ ... ¡… ¡ ... ¡… ¡ > ¡6,000 ¡ LOC ¡ <100 ¡LOC ¡

  33. DEMO ¡ • Sequen(al ¡tests ¡to ¡ validate ¡the ¡model ¡ • Parallel ¡tests ¡to ¡find ¡ race ¡condiAons ¡

  34. Bug ¡#1 ¡ insert_new(Name, ¡Objects) ¡-­‑> ¡Bool ¡ Prefix: Types: ¡ open_file(dets_table,[{type,bag}]) --> Name ¡= ¡name() ¡ Objects ¡= ¡object() ¡| ¡[object()] ¡ dets_table Bool ¡= ¡bool() ¡ Parallel: 1. insert(dets_table,[]) --> ok 2. insert_new(dets_table,[]) --> ok Result: no_possible_interleaving

  35. Bug ¡#2 ¡ Prefix: open_file(dets_table,[{type,set}]) --> dets_table Parallel: 1. insert(dets_table,{0,0}) --> ok 2. insert_new(dets_table,{0,0}) --> …time out… =ERROR ¡REPORT==== ¡4-­‑Oct-­‑2010::17:08:21 ¡=== ¡ ** ¡dets: ¡Bug ¡was ¡found ¡when ¡accessing ¡table ¡dets_table ¡

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend