Saturday, July 9, 2016

Kata: Ohce in Clojure using outside-in TDD with Midje

I did the Ohce kata in Clojure using outside-in TDD with Midje.

I started by writing a nearly end-to-end test for the scenario of running ohce during the morning:

In this test I used Midje's unfinished and provided macros to stub the hour-fn and read-input functions and with-out-str to capture the any printed lines.

Using Midje's future-facts macro I avoided seeing this acceptance test failing every time the tests were run, instead I saw a reminder message like this one:

Next I started testing ohce at the unit level. These are the resulting facts:

For these facts I used a fake implementation of the Notifier protocol:

which captured the arguments with which the functions of the protocol implementation were being called:

I could have used Midje's defrecord-openly and provided macros instead but I didn't like having to use defrecord-openly in production code.

The statement above is wrong. It is not necessary at all to use defrecord-openly in your production code in order to mock a protocol. See how it's done in this other post: Revisited Kata: Using Midje's defrecord-openly to mock a protocol in Ohce.

Another thing to notice in that test is the use of Midje's metaconstants to avoid the facts knowing about the "shape" of data (where it was possible to do it).

Well, those facts lead to the following code:

Then I started applying TDD on the next level to write ConsoleNotifier, an implementation of the Notifier protocol:

and the select-greeting function (select-by-day-period in this case):

Once those tests were passing, I just had to inject a ConsoleNotifier record and the select-greeting function into ohce to make the acceptance test pass:

I also added two other scenarios (running ohce during the afternoon and during the night).

A curious thing to notice is that I couldn't use partial with select-greeting if I wanted the provided macro to work with hour-fn, that's why I used a lambda instead. Due to the same problem I also had to wrap the read-input function inside a lambda.

Then to be able to really run ohce on the console I just had to write a real hour-fn function (tested on the REPL):

and create a -main function (read-input is just the Clojure's read-line function):

This is an example of running ohce:

I committed after each passing test and each tiny refactoring, so that you can follow the process if you feel like. You can check the commits step by step here.

You can find the resulting code in this GitHub repository.

Doing this kata helped me to learn a lot of new things about Midje.

No comments:

Post a Comment