Testing Deep Structures With Midje
Here's a Midje fact:
(fact "adding two and two produces four" (+ 2 2) => 4)
Midje introduces the
=> (which I read produces): the expression to the left of
=> is evaluated and compared with the expression on its right, using Midje's notion of extended equality. The extended part is useful to us here:
(fact "adding two and two produces a positive number" (+ 2 2) => pos?)
If the result of the right side is a function, it is applied to the result of the left side to see if the test passes. In this case
(pos? (+ 2 2)) is true, so the test passes.
So why not write
(pos? (+ 2 2)) => true? There is a difference in what is printed when the test fails: the first prints this:
Actual result did not agree with the checking function. Actual result: -98 Checking function: pos?
while the second prints:
Expected: true Actual: false
The first form helps us out because it gives us more information about what happened when a test fails.
In Avi, the editor's state is a large, nested map containing open buffers, the cursor position, the current viewport position, the contents of the status line, the editor's mode and more.
Each time an event (usually a keystroke) is received, the editor state is advanced to the next state. For example, the editor might have a key
:mode with a value of
:normal, but after advancing the state by applying the ":" character,
:mode might be
The usual way to test this might be:
(fact "`:` enters command-line mode" (:mode (editor :after ":")) => :command-line)
editor is a testing helper function which allows super-concise tests.)
If this test fails, we'll see:
: enters command-line mode"
This doesn't tell us much, does it? On the other hand, we can write a
Expected: :command-line Actual: :normal
(defn mode [expected-mode] (fn [editor] (= (:mode editor) expected-mode)))
and rewrite our fact:
(fact "`:` enters command-line mode" (editor :after ":") => (mode :command-line))
Now, when the test fails, we might be able to see, for example, that a ":" was literally inserted into the buffer–or that it wasn't.
I think this warrants a general rule:
When you find yourself doing gyrations on the left side of
=>, write a > Midje checker instead.
It's also possible that you could be testing through a different function which produces a "more-inner" data structure – but first consider whether that function's signature is stable enough, or you will cause yourself pain later.