An idea about testing inner functions in Clojure

While working on the “sweet” interface for Midge, I wrote this function:

metavar? and form-branch? are only useful within this function. I would have preferred to write it like this:

I didn’t because I wanted those two functions tested before I relied on them. So I need a format for testing inner functions. I’ve sketched out a format and done (by hand) the transformation required to make it work.

I’ll start explaining it with this simple example:

Before dealing with the daunting complexity of multiplication, I want to test summer with something like this:

(I’m using the Midje sweet notation here. Read it as “It’s a fact that (within (outer 1 2)), (summer) produces 3.”)

To make this work, I’d redefine the defn macro for the duration of a test and have it produce a little extra metadata:

I’m stashing away a function derived from summer. It creates the same lexical environment that outer does, and returns a function to call. Here’s the macro that would expand a within, together with a sample expansion:

The expanded form is a little opaque, so here are the three steps:

  1. Retrieve the environment setting function from outer’s metadata.
  2. Call it with the outer arguments.
  3. Within that environment, call summer.

What if a later inner function uses a previously-defined one? Like this:

One option would be to drag the earlier parts of the let into the metadata:

In that case, the test would look like this:

This test is a little not-thrilling because it’s clearer what multiplier does if you can see how it relies on summer. That could look like this:

However, dragging the previous let clauses into the metadata has to be done anyway (in case non-function values are bound), so I’d be inclined not to gild this lily.

Creating the metadata wouldn’t be too hard in the common case where the let is the outermost form in the function’s definition. I doubt I could be persuaded to care about other cases.

6 Responses to “An idea about testing inner functions in Clojure”

  1. links for 2010-08-03 « Blarney Fellow Says:

    […] Exploration Through Example » Blog Archive » An idea about testing inner functions in Clojure (tags: clojure macros bindings) […]

  2. Today in the Intertweets (August 2nd Ed) | disclojure: all things clojure Says:

    […] inner functions in #clojure (here, via @marick) — Brian Marick is working on Midge, a mocking library for Clojure. This post a […]

  3. What you need to be reading this weekend: 08/06/2010 — Scrumology Pty Ltd Says:

    […] – Measuring Up: Authors note: I wrote this article in 2002.  At that time, Agi.. RT @marick – An idea about testing inner functions in Clojure: While working on the “sweet….Big banks need IT reform almost as badly as regulatory change RT @estherderby – Six Ways that […]

  4. snewman Says:

    I’ve struggled with this - using inner functions and wanting to stub them out/test them separately.

    Variously, I’ve not bothered (which I dislike), injected them (which is very non-idiomatic) or more often pulled out lots of little named functions just so I can test them by themselves and then stub them out when testing the higher-level functions that use them. None of those solutions seemed good to me. Having something like you describe would be very useful - is this just thinking out loud, or something you’re going to build in to midje?

  5. snewman Says:

    Oh, as a ps, the Gist embedding does a good job of syntax highlighting, but one downside is that the code doesn’t appear in your RSS feeds (e.g. when viewing your content in Google Reader etc). An alternative might be to use something like syntaxhighlighter: http://code.google.com/p/syntaxhighlighter/. This just decorates pre blocks in your post, so the raw HTML still contains the code listing, but you still get the nice coloring. And yes, it supports Clojure :-)

  6. Brian Marick Says:

    I’ve saved up the transformations I did by hand. Had I a formal roadmap for Midje, this would be on it.

Leave a Reply

You must be logged in to post a comment.