Baby steps in TDD with Clojure and Midje

I’ve got an idea for an app. It’s going to be a GUI app and was wondering how to start off. I’ve lately been impressed by TDD in Java (thanks @krzysztofjelski!) and thought about giving it a go to build the app with Clojure. TDD is language-agnostic, so Clojure should work fine too, shouldn’t it? When I googled “tdd clojure” I came across Midje.

From Midje’s project.clj:

“A TDD library for Clojure that supports top-down (‘mockish’) TDD, encourages readable tests, provides a smooth migration path from clojure.test, balances abstraction and concreteness, and strives for graciousness.”

The official web site of Midje says: “Midje is a test framework for Clojure.”

That seemed the right tool for my needs.

Since I’m using lein, the other google search was for “midje lein” and ended up with Lein midje which turned out not useful for the warm-up of mine into TDD.

Anyway, the project is managed by lein so a small change in project.clj was needed – add

[midje "1.3.1"]

to

:dependencies

and you should be able to run

lein repl

with midje available to

(use 'midje.sweet)

. I was on my way towards TDD happiness in Clojure. Or, again, so thought I.

user=> (use 'midje.sweet)
nil
user=> (fact)
true
user=> (fact (+ 1 1) => 2)
true

That was all I needed to get up and running with TDD. Or so thought I.

When I ran the following code, I realized REPL is about to change the way I consider programming constrained by the change-compile-test development cycle (not to mention red-green-refactor one). I’m now leaning towards thinking about REPL as a kind of a TDD environment and Midje doesn’t seem to help much. It’s a part of REPL already – no, not Midje, but the idea of TDD.

user=> (fact (parse-input "1") => 1)
CompilerException java.lang.RuntimeException: Unable to resolve symbol: parse-input in this context, compiling:(NO_SOURCE_PATH:7) 
user=> (defn parse-input [s]
(Integer/parseInt s))
#'user/parse-input
user=> (fact (parse-input "1") => 1)
true

I now tend to believe TDD in Clojure may be a little bit tricky and with almost no prior experience in TDD it may get even tricker. I’ll have to study the matters a little bit further before drawing conclusions, but the short meetup with Midje led me to believe TDD might not be needed while in REPL. It looks like REPL may have taken a little of an area covered by TDD in Java.

Be Sociable, Share!
This entry was posted in Languages.

6 Responses to Baby steps in TDD with Clojure and Midje

  1. Konrad Garus says:

    TDD still makes much sense in Clojure. REPL is a nice thing that consistently provides feedback, but it doesn’t have many cool features of TDD.

    With REPL you’re happy if you hack a quick and dirty solution that may not work well with border cases. With TDD you’ll end up writing a test for every border case you can think of.

    TDD should leave you with a set of small tests that cover each and every feature, which you run over and over again and in future can serve both as documentation, and as protection from regression.

    It also leads (at least in my case…) to simpler and more readable API.

    Finally, the development cycle is pretty different with TDD thanks to mocking and focusing on one area at a time.

    PS. Instead of googling “midje lein”, try clojars.org.

  2. Thomas says:

    Have you tried running it in the lazy test mode:

    lein midje --lazytest

    Maybe that is what you are looking for.

    Thomas

  3. Jacek Laskowski says:

    Thanks for the comments. I can’t add more to it as I’m quite new to all the tools, but will soon. Thanks Thomas and Konrad!

  4. Steve says:

    I also like mucking around in the REPL. I do it with Ruby and Python as well. For TDD, however, you have to look at the longer term. A month from now, with a different REPL session, what kind of safety net do you have to support changing that anonymous function? That’s at least one benefit to TDD.

    I think that BDD (behavior driven development) folks take it further (whether or not it needs to be called “BDD” instead of “TDD”). In this case, TDD is not just about getting your code to work correctly. It’s also about having executable documentation that shows how your code should be used (appropriate inputs and expected outputs) that can never get out of sync with your source code (as comments can).

    With this view in mind, tests should be written that describe how your code should be used…not just put it through its paces. You don’t just want to prove the code works; you want to document how it should be used as well. I find this useful for so-called “one off” code as well…I almost always want to cannibalize part of it at some point later and I need to figure out what it does or can be made to do. If it has existing tests, this is easier.

    When I return to code in a month or more, it is always easier for me to understand the code that I wrote tests for than the code I merely put comments in (or just hacked together in the REPL).

    Of course, your mileage may vary.

    • Jacek Laskowski says:

      Hi Steve,

      Thanks for the comment. I’ve nothing to add – I’m simply speechless and would rather stay still and listen, and ultimately absorb in its entirety. I’m not joking. I liked your comment! I’m on my way to find out how far I can go with TDD, Clojure and REPL so I’m sure I’ll get back to the comment once more once I’m done with it.

      Jacek

  5. Brian Marick says:

    You might find this video of a TDD session helpful. It shows that you can get something very like a fast-feedback REPL experience with TDD. (In this case, I’m using Emacs Emacs midje-mode, so you can’t replicate that experience if you’re not an emacs user. The autotest mode that Thomas noted above is reasonably close to it.

Leave a Reply

%d bloggers like this: