Recently I was writing some data mining Clojure code which needed to parse a log file and do some transforms of the data. Some of the transforms were dependent on data found across multiple lines. There was no ordering or proximity guarantees to these lines.
This required the code to handle a variety of situations. After writing a couple simple tests and getting those passing I wanted to more extensively test my solution. I was lazy though and did not want to hand code all of the potential orderings. Enter permutations
.
permutations
is a function out of clojure.contrib.combinatorics. As the name suggests, you give it a collection and it returns a lazy sequence containing all the different permutations of the elements in that collection. An example is below.
1 2 3 4 5 |
|
You can already see where this is going. I was able to use permutations
to generate all the potential different orderings of the input. This saved me the trouble of having to do that by hand.
One difficulty of generating test inputs pragmatically is telling what sort of inputs caused it to fail. To get around this I used the rarely used (at least in code I’m working on) second argument of clojure.test’s is
. This second argument is a message that prints on a failure.
Below is a contrived example of using permutations
to test an obviously wrong silly-add
function. silly-add
is defined below.
1 2 3 4 5 6 |
|
Below is a test that uses permutations
to exercise silly-add
with all the potential orderings three input numbers. Note that it takes advantage of the second argument to is
. Without this we would not know what input caused the failure.
1 2 3 4 5 6 7 |
|
Running the test we see that there is clearly an error.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
permutations
saved me a bit of time and let me test some situations that I otherwise would not have tested. This actually exposed a subtle bug in my code. Hopefully it can do the same for you.