DEV Community

Cover image for Intro to Property-Based Testing

Intro to Property-Based Testing

Jason Steinhauser on June 09, 2018

Property-based tests make statements about the output of your code based on the input, and these statements are verified for many different possib...
Collapse
 
ericnormand profile image
Eric Normand

Hey Jason,

Very nice article!

I really like that you focus on the mathematical properties. That's where property-based testing really shines. Just like unit tests help us write testable code, property-based tests help us write operations with simple and useful properties.

A couple of comments:

a = a * 1 = a * 1 * 1 is idempotent. 1 is also the identity of *, which is another property.

Idempotence (function f is idempotent): f(a) = f(f(a))

Examples:

Math.abs(x) = Math.abs(Math.abs(x))
hashmap.merge({a:1}) = hashmap.merge({a:1}).merge({a:1})

Identity (i is the identity of f): f(a, i) = a

Examples:

a + 0 = a
a * 1 = a
usernames.append([]) = usernames
hashmap.merge({}) = hashmap
Bool1 && True = Bool1

There's also the mathematical idea of zero. a * 0 = 0. It's another cool property.

Zero (z is the zero of f): f(a, z) = z
intersect(set1, EmptySet) = EmptySet
Bool1 && False = False

I think the example you gave for associativity (with sorting and filtering) is actually an example of commutativity since it shows that order doesn't matter between sorting and filtering.

Associativity examples:

hashmap1.merge(hashmap2.merge(hashmap3)) = (hasmap1.merge(hashmap2)).merge(hashmap3)
list1.append(list2.append(list3)) = (list1.append(list2)).append(list3)

Commutativity examples:

Math.max(a, b) = Math.max(b, a) (though this one is also associative :)
Bool1 && Bool2 = Bool2 && Bool1 (this one is associative too)
average(a, b) = average(b, a)

Again, this was an awesome article!

Rock on!
Eric

Collapse
 
jdsteinhauser profile image
Jason Steinhauser

Hey Eric,

First off, I geeked out again when I saw I had a comment from you. I've loved several of your articles on Clojure!

Secondly, I think your critiques are correct. I misused idempotency slightly, and my associative example is actually commutative. I definitely appreciate the clarification and additional examples? Would you mind if I added those to the article?

Thanks again for the complements and clarifications, and keep up the good work at PurelyFunctional.tv!

Collapse
 
ericnormand profile image
Eric Normand

Hey Jason,

Sorry I didn't reply to this sooner. Be my guest and reuse the examples.

Rock on!
Eric

Collapse
 
quii profile image
Chris James

This is such a better writeup than the one I just published! Haha, amazing work

Collapse
 
jdsteinhauser profile image
Jason Steinhauser

Well thank you! I have your article on my reading list, so I'll be sure to check it out πŸ˜ƒ

Collapse
 
Sloan, the sloth mascot
Comment deleted
Collapse
 
jdsteinhauser profile image
Jason Steinhauser

Thanks! I'm glad you were able to find value in it :-)

Collapse
 
ben profile image
Ben Halpern

Absolutely superb writeup πŸ™Œ

Collapse
 
jdsteinhauser profile image
Jason Steinhauser

Why thank you! When I saw this email notification I may have geeked out a bit

Collapse
 
akotek profile image
Aviv Kotek • Edited

Finally an article who doesn't copy/paste clojure-docs :p
liked the property-patterns, Thanks!

Collapse
 
dotnettec profile image
Ravi Kumar

Very nice article!

Thanks.
Ravi (DotNetTec)