Skip to content

Commit

Permalink
Junit formatter for Midje.
Browse files Browse the repository at this point in the history
  • Loading branch information
josephwilk committed Apr 9, 2013
1 parent b5cc711 commit db9cea7
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 0 deletions.
88 changes: 88 additions & 0 deletions src/midje/emission/plugins/junit.clj
@@ -0,0 +1,88 @@
(ns ^{:doc "JUnit formatter for Midje output"}
midje.emission.plugins.junit
(:use
[midje.emission.util])
(:require [midje.data.fact :as fact]
[midje.emission.state :as state]
[midje.emission.plugins.silence :as silence]
[midje.emission.plugins.default-failure-lines :as lines]
[clojure.string :as str]
[clojure.xml :as xml :only [emit-element]]))

(def report-file "report.xml")

(defn log-fn []
(fn [text] (spit report-file text :append true)))

(defn- log [string]
(let [log-fn (log-fn)]
(log-fn string)))

(defn- reset-log []
(spit report-file ""))

(defn def-fact-cache []
(defonce last-fact (atom {})))

(defn- fact-name [fact]
(or (fact/name fact)
(fact/description fact)
(str (fact/file fact) ":" (fact/line fact))))

(defn pass []
(log
(with-out-str
(xml/emit-element @last-fact))))

(defn- testcase-with-failure [failure-map]
(let [testcase @last-fact
failure-content (str "<![CDATA[" (apply str (lines/summarize failure-map)) "]]>")
fail-type (:type failure-map)
fail-element {:tag :failure
:content [failure-content]
:attrs {:type fail-type}}
testcase-with-failure (assoc testcase :content [fail-element])]
testcase-with-failure))

(defn escape [s]
(if s
(str/escape s {\' "\\'"})
""))

(defn fail [failure-map]
(let [testcase (testcase-with-failure failure-map)]
; FIXME: currently there is a bug in midje that prevents us emitting this map as xml
;(xml/emit-element testcase)

(log (str "<testcase classname='" (-> testcase :attrs :classname) "' name='" (-> testcase :attrs :name) "'>\n"))
(log (str "<failure type='" (-> testcase :content first :attrs :type) "'>"))
(log (-> testcase :content first :content :first))
(log "</failure>\n")
(log "</testcase>")))

(defn starting-to-check-fact [fact]
(let [fact-namespace (str (fact/namespace fact))
fact-name (fact-name fact)]
(reset! last-fact {:tag :testcase
:attrs {:classname (escape fact-namespace) :name (escape fact-name)}})))

(defn starting-fact-stream []
(def-fact-cache)
(reset-log)
(log "<testsuite>"))

(defn finishing-fact-stream [midje-counters clojure-test-map]
(log "</testsuite>"))

(defn make-map [& keys]
(zipmap keys
(map #(ns-resolve *ns* (symbol (name %))) keys)))

(def emission-map (merge silence/emission-map
(make-map :fail
:pass
:starting-fact-stream
:finishing-fact-stream
:starting-to-check-fact)))

(state/install-emission-map emission-map)
53 changes: 53 additions & 0 deletions test/midje/emission/plugins/t_junit.clj
@@ -0,0 +1,53 @@
(ns midje.emission.plugins.t-junit
(:use [midje sweet util test-util])
(:require [midje.emission.plugins.junit :as plugin]
[midje.config :as config]
[midje.emission.plugins.default-failure-lines :as failure-lines]))

(defn innocuously [key & args]
(config/with-augmented-config {:emitter 'midje.emission.plugins.junit
:print-level :print-facts}
(captured-output (apply (key plugin/emission-map) args))))

(def test-fact
(with-meta (fn[]) {:midje/name "named" :midje/description "desc" :midje/namespace "blah"}))

(def test-failure-map
{:type :some-prerequisites-were-called-the-wrong-number-of-times,
:namespace "midje.emission.plugins.t-junit"})

(fact "starting a fact stream opens a <testsuite>"
(innocuously :starting-fact-stream) => (contains "<testsuite>")
(provided
(plugin/log-fn) => #(println %)))

(fact "closing a fact stream closes </testsuite>"
(plugin/def-fact-cache)

(innocuously :finishing-fact-stream {} {}) => (contains "</testsuite>")
(provided
(plugin/log-fn) => #(println %)))

(fact "pass produces a <testcase> tag"
(plugin/def-fact-cache)
(plugin/starting-to-check-fact test-fact)

(innocuously :pass) => (contains "<testcase classname='blah' name='named'/>")
(provided
(plugin/log-fn) => #(println %)))

(fact "failure produces a <testcase> tag"
(plugin/def-fact-cache)
(plugin/starting-to-check-fact test-fact)

(innocuously :fail test-failure-map) => (contains "<testcase classname='blah' name='named'>")
(provided
(plugin/log-fn) => #(println %)))

(fact "failure also produces a <failure> tag"
(plugin/def-fact-cache)
(plugin/starting-to-check-fact test-fact)

(innocuously :fail test-failure-map) => (contains "<failure type=':some-prerequisites-were-called-the-wrong-number-of-times'>")
(provided
(plugin/log-fn) => #(println %)))

0 comments on commit db9cea7

Please sign in to comment.