JUnit output for Clojure tests

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 clojure.test
            [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)
  (binding [clojure.test/*report-counters* nil]
    (xml-report m)))

You have to bind *report-counters* to nil when executing one of the reporters to prevent each assertion from getting counted twice. Ideally this would be handled by eftest, but the design of clojure.test makes it hard to do. Check out eftest’s issue 23 for discussion.

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.

Update 2017-09-19: Added the binding for *report-counters*. Thanks to Andrew Gnagy for pointing out this problem.

Comments or questions? Send me an e-mail.