Property-based Testing with PropEr
PropEr is a QuickCheck-inspired property-based testing tool for Erlang. In contrast to traditional testing methodologies, the tester only has to provide the generic structure of valid inputs and some properties, which specify the relation between input and output. The testing tool will then produce progressively more complex valid inputs and compare the results it gets to what it expected (based on the defined properties).
PropEr is one such testing tool for Erlang. It is open-source and supports Erlang R15B01+.
Assuming you already have your $ERL_LIBS
set up, you can simply run the following commands to install PropEr and make it available globally.
|
|
After that, you can use PropEr in all your Erlang projects.
I like using EUnit as the runner for my property based tests. There are some caveats, but all in all it works without any issues.
What I don’t like is defining my property-based tests in the same module as my unit tests, because it feels wrong to do so. I generally define one _test_
function that calls proper:module/2
.
|
|
This allows me to have all of the unit tests in example_utils_test
and all of the property-based tests in example_utils_prop
.
Let’s write a simple property-based test for the binary_join
function I’ve [introduced in February]({{ site.url }}/posts/joining-a-list-of-binaries-in-erlang/).
|
|
This will test if the size of the output of example_utils:binary_join/2
is what we would expect:
- Zero: If the list of binaries to join is empty
- Size of the first element in the list: If the list of binaries to join only has one element
- Sum of the size of all elements in the list, plus the size of the separator times the number of elements (minus one, because there will be no trailing separator): All other cases
The ?FORALL
macro takes three aguments:
- Tuple of variables which will be set to the genrerated inputs and can be accessed in the property
- Tuple of type specifications for the inputs that will be generated
- The property that will be tested
If you actually run the test, the output will look something like this:
Testing example_utils_prop:prop_binary_join/0
....................................................................................................
OK: Passed 100 test(s).
By default, PropEr will generate 100 random valid inputs and compare the output to the (length) properties we defined above.
PropEr can do much more than what I’ve shown here. While there are not many examples available, you should be able to get going using the documentation.