Mathias Verraes
April 06, 2016
2.6k

# Property Based Testing

5min lightning talk for the SoCraTes Belgium meetup and CukeUp London.

April 06, 2016

## Transcript

4. ### -- Tests double 1 `should_be` 2 double 2 `should_be` 4

-- Implementation double x | x == 1 = 2 | x == 2 = 4
5. ### A property of double double_is_always_even :: Int -> Bool double_is_always_even

x = even (double x)
6. ### > quickCheck double_is_always_even Failed: 0 (after 1 test) Exception: Non-exhaustive

patterns in function double

8. ### quickCheck double_is_always_even Passed: 0 Passed: 1 Passed: -3 Passed: -1

(...) Passed: -58 Passed: 89 +++ OK, passed 100 tests.
9. ### More properties of double double_compare_to_input x | x > 0

= double x > x | x < 0 = double x < x | x == 0 = True double_minus_input x = double x - x == x
10. ### Distributivity Law reverse_is_distributive xs ys = reverse (xs++ys) == reverse

xs ++ reverse ys
11. ### > quickCheck reverse_is_distributive Passed: [] [] Passed: [] [1] Passed:

[1] [] Failed: [3,-3] [0,2,0] Passed: [] [0,2,0] Failed: [3] [0,2,0] Failed: [-3] [0,2,0] Failed: [0] [0,2,0] Failed: [0] [2,0] (...) Falsifiable (after 4 tests and 6 shrinks): [0] [1]
12. ### Oops... reverse_is_distributive xs ys = reverse (xs++ys) == reverse ys

++ reverse xs
13. ### Passed: [] [] Passed: [1,-2] [0] Passed: [-2] [] (...)

Passed: [-34,44,-58,-41,-17,-53,-14,27,54,46,-10,-46,-20,46] [-9,-32,-47,50,43,-47,-43,-61,37,4,-59,48,34] +++ OK, passed 100 tests.
14. ### Split 1 -- define split :: Char -> String ->

[String] -- so that split '@' "[email protected]" == ["foo","example.com"] split '/' "/usr/include" == ["", "usr", "include"] 1 https://www.schoolofhaskell.com/user/pbv/an-introduction-to-quickcheck-testing
15. ### -- splitting an empty list results in an empty list

split char [] = [] split char str | null after = before : [] | otherwise = before : split char (tail after) where before = takeWhile (/=char) str after = dropWhile (/=char) str
16. ### Property: Splitting and unsplitting -- test unsplit '@' ["foo","example.com"] ==

"[email protected]" unsplit '/' ["", "usr", "include"] == "/usr/include" --implementation unsplit :: Char -> [String] -> String unsplit char = concat . intersperse [char]
17. ### -- property unsplit_inverses_split str = forAll (elements str) (\char ->

unsplit char (split char str) == str)
18. ### > quickCheck unsplit_inverses_split Passed: "" Passed: "\252\210" '\252' Passed: "\163^\EOT"

'\163' Passed: "v\RSs" 'v' Failed: "y" 'y' Failed: "a" 'a' Falsifiable (after 6 tests and 1 shrink): "a" 'a'
19. ### split 'a' "a" == [""] unsplit 'a' [""] == ""

-- should be: split 'a' "a" == ["", ""] unsplit 'a' ["", ""] == "a"
20. ### Modify the deﬁnition of split split char [] = []

... -- becomes split char [] = [""] ... > quickCheck unsplit_inverses_split +++ OK, passed 100 tests.
21. ### Property Based Testing → test lots of random cases cheaply

→ encourage thinking about general properties Thanks :-) @mathiasverraes