100 likes | 262 Vues
Testing in Erlang. Different testing tools. EUnit (standard lightweight xUnit solution for Erlang) Common Test (OTP based distributed testing tool) Qucik Check (property based testing tool). A simple problem (deleting from a list). 4>lists:delete(2,[1,2,3]). [1,3]
E N D
Different testing tools • EUnit (standard lightweight xUnit solution for Erlang) • Common Test (OTP based distributed testing tool) • Qucik Check (property based testing tool)
A simple problem (deleting from a list) • 4>lists:delete(2,[1,2,3]). • [1,3] • 5>lists:delete(4,[1,2,3]). • [1,2,3] • We should write a test for delete like this: • delete_present_test()-> • lists:delete(2,[1,2,3])==[1,3]. • delete_absent_test()-> • lists:delete(4,[1,2,3])==[1,2,3].
Problems with xUnit style solution • Lots of work to create “good” tests and various test cases • The code as good as your tests • Can’t create and validate with formal specification
What other solution is possible • We’d like to generalise our tests • We’d like to generate or run different cases automatically • We’d like to avoid the “human failure” from the system (if it is even possible) • We’d like to write something like this: • prop_delete(I,L)-> • notlists:member(I,lists:delete(I,L)).
QuickCheck is the solution • With QuickCheck we can test our property automatically in many cases without the effort of specifying each case manually • So we can write QuickCheck property like this: • prop_delete()-> • ?FORALL({I,L},{int(),list(int())}, • notlists:member(I,lists:delete(I,L))).
Test data generators • Instead of the logically meaning QuickCheck interprets the expression as a data generator • int() is a generator of random integers • list(int()) is a generator of random lists containing integers • {int(), list(int)} produces pairs of integer and a list of integers • ?FORALL binds {I,L} to the pattern {int(), list(int)}
Running the test • eqc:quickcheck(examples:prop_delete()). • Works fine! • eqc:quickcheck(eqc:numtests(1000,examples:prop_delete())). • Fails… • Diagnosis and shrinking
Conditional properties • ?IMPLIES • prop_delete()-> • ?FORALL({I,L},{int(),list(int())}, • ?IMPLIES(no_duplicates(L), • notlists:member(I,lists:delete(I,L)))). • no_duplicates(L)->lists:usort(L)==lists:sort(L).
Custom generators • We can create our own generators • ulist(Elem)-> • ?LET(L,list(Elem), • lists:usort(L)).