This is a weblog about computing, culture et cetera, by . Read more.


JUnit output for Clojure tests

I’m trying to get my Clojure testing ducks in a row.

I’m trying to get my Clojure testing ducks in a row.

In January, I wrote about the features I’d like to have in a Clojure test runner. One of them was JUnit XML reports for the test results. I’ve since contributed a JUnit reporter to Eftest, the test runner library developed by James Reeves.

I had two goals. The first was to support running tests in parallel, which is what Eftest does by default. The second was to produce human-readable output and a JUnit report at the same time. Both of the goals are accomplished by Eftest 0.3.1.

For the second goal, you have to write your own reporting function that calls both the pretty reporter (or the progress reporter, or whatever you like) and the JUnit reporter. Then you can use eftest.report/report-to-file to redirect one of them to a file. Here’s how it goes:

(ns my-project.report
  (:require [eftest.report :refer [report-to-file]]
            [eftest.report.junit :as junit]
            [eftest.report.pretty :as pretty]))

(def xml-report
  (report-to-file (junit/report "test-results.xml")))

(defn report [m]
  (pretty/report m)
  (xml-report m))

Now run your tests with {:report my-project.report/report} and you’ll get Eftest’s colorful exception reports in the console and a JUnit report in the file test-results.xml.

Test tagging and other features

Another feature on my list was filtering tests by tags. Already in January, Eftest had the ability to filter tests with an arbitrary function. Since then, James has created a Leiningen plugin for Eftest and Facunda Olano has implemented the test selectors supported by lein test.

Output catching and the test slowness report are still missing. Output catching is a bit hairy if you want to deal with loggers, but I already wrote a version that catches any output written to *out*. It might be the 80/20 solution. I’ll send a pull request soon. The slowness report should be easy to implement with a reporter function as well.

I think Eftest is going to be the test runner I wished for. I recommend it, and if you want to use it with Boot, boot-alt-test is a wrapper for it.


prog1 in Clojure

Clean your code with this one weird macro trick.

Clean your code with this one weird macro trick.

When programming Clojure, sometimes you need the equivalent of Common Lisp’s prog1 macro. It’s like Clojure’s do except that it returns the value of the first form, not the last one.

You could depend on useful, which calls it returning:

(defmacro returning
  "Compute a return value, then execute other forms for side effects.
  Like prog1 in common lisp, or a (do) that returns the first form."
  [value & forms]
  `(let [value# ~value]
     ~@forms
     value#))

Of course, when you’re in a hurry, there’s no time for adding new dependencies. There’s not even time to write your own inline version of the macro. Besides, they say that you shouldn’t ever write your own macros. So what do you do? You compose doto and do:

(doto x
  (do
    (y)
    (z)))
;; returns x

But maybe instead of x you have (a complicated form) and you want to give its result a name. Luckily there’s as->.

(doto (a complicated form)
  (as-> x 
    (do
      (y x)
      (z x))))

When you’re debugging a long -> thread, a print function that returns the printed value would be handy so you could insert it in the middle of the chain. This is of course exactly what tools.trace is for. But again, who has time for adding dependencies? Just use doto.

(-> thing
    do-something-1
    do-something-2
    (doto prn)
    do-something-3)

By the way, the other day I wrote this macro that resembles cond->:

(defmacro if-> [expr cond then else]
  `(let [e# ~expr]
     (if ~cond (-> e# ~then) (-> e# ~else))))

I used it with a builder object. The code looked something like this:

(-> (Builder.)
    (.withSetting "password" "kissa2")
    (if-> production-mode?
      (.useProductionMode)
      (.useTestingMode))
    (.build))

Can somebody figure out how to do that nicely without writing a macro?


Darkroom update

It’s Easter holiday and I’m looking forward to photographing Haronmäki again. This time it’s going to be in black and white, shot in medium format.

I’ve been practicing darkroom printing for half a year now and I’m finally starting to get somewhere. Or at least I’m not making mistakes every time I go the darkroom. I’m starting to get consistent results and sometimes I even thinking I’m finding my own “voice”. I had especially good time with photographing ice this winter.

I’ve wasted a lot of paper, but luckily I’ve ruined only two rolls of film. Lesson learned: developing two films at once is a great way to ruin two films at once.


For more posts, see archive.