4 August 2021

Threading Speclj Assertions

Just a crazy idea

AssertEqual vs. ShouldEqual

As a newcomer to Clojure I'm getting to know speclj, which generally employs test assertions of the following form:

Placing the 'expected' value before the 'actual' value is reminiscent of the 'assert-equal' method from well-established xUnit test tools often used when practicing the discipline of TDD.

In tools created by the BDD community, assertions often reverse the expected/actual parameters for fluency in reading. So, something like:

These two forms really are functionally identical. Which one you employ is really just a matter of preference and style.

Thread-last Macro (->>)

The thread-last macro has the effect of turning nested function calls into what appear to be simple lists of invocations in left-right/top-down order. So, this form:

would, with the application of the thread-last macro, become:

Idea: ->> + should=

Today's "ah-hah!" moment came when I realized that the thread-last macro would allow a test author to pick either style when writing assertions in speclj. So, this traditional rendering:

Could become:

You might read the code of the assertion ((+ 1 2) (should= 3)) from left to right like this:

When you add 1 and 2 it should equal 3.

Specifically, here's what appeared during my latest rehearsal of the bowling game kata:

(describe "bowling game kata"
  (it "gutters" (->> (roll-many 20 0) score (should= 0)))
  (it "ones   " (->> (roll-many 20 1) score (should= 20)))
  (it "spare  " (->> (concat [5 5] [3 1]) score (should= 17)))
  (it "strike " (->> (concat [10] [3 4] [1 0]) score (should= 25)))
  (it "perfect" (->> (roll-many 12 10) score (should= 300))))

A transcription of an out-loud reading of these assertions might result in the following prose:

When you roll twenty 0s the score should equal 0.
When you roll twenty 1s the score should equal 20.
When you roll a spare, then 3, then 1, the score should equal 17.
When you roll a strike, then 3, 4, 1, 0, the score should equal 25.
When you roll twelve strikes in a row the score should equal 300.