Skip to content

Commit

Permalink
Merge pull request #69 from alpian/master
Browse files Browse the repository at this point in the history
Customizing reporters
  • Loading branch information
slagyr committed Nov 11, 2013
2 parents 68186a7 + 5b1a05d commit 1a55452
Show file tree
Hide file tree
Showing 4 changed files with 169 additions and 2 deletions.
8 changes: 7 additions & 1 deletion spec/speclj/config_spec.clj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(ns speclj.config-spec
(:require ;cljs-macros
[speclj.core :refer [describe it should-not= should= should-throw should-not-contain]]
[speclj.core :refer [describe it should-not= should= should-throw should-not-contain should-be-same]]
[speclj.platform])
(:require [speclj.config :refer [load-runner load-reporter default-config
parse-tags config-mappings *tag-filter* config-bindings]]
Expand Down Expand Up @@ -37,6 +37,12 @@

(it "throws exception with unrecognized reporter"
(should-throw exception "Failed to load reporter: blah" (load-reporter "blah")))

(it "can be given a pre-fabricated reporter"
(let [pre-fabricated-reporter (speclj.report.silent/new-silent-reporter)
reporter (load-reporter pre-fabricated-reporter)]
(should-not= nil reporter)
(should-be-same reporter pre-fabricated-reporter)))

(it "converts tag input to includes/excludes"
(should= {:includes #{} :excludes #{}} (parse-tags []))
Expand Down
73 changes: 73 additions & 0 deletions spec/speclj/report/clojure_test_spec.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
(ns speclj.report.clojure-test-spec
(:require ;cljs-macros
[speclj.core :refer [around before context describe it should should= should-contain with]]
[speclj.platform :refer [new-exception new-failure new-pending]])
(:require [clojure.string :as str]
;cljs-include [goog.string] ;cljs bug?
[speclj.components :refer [new-description new-characteristic install]]
[speclj.config :refer [*color?* *full-stack-trace?*]]
[speclj.platform :refer [format-seconds]]
[speclj.report.clojure-test :refer [new-clojure-test-reporter]]
[speclj.reporting :refer [report-description report-pass report-pending
report-fail report-error red green yellow grey report-runs]]
[speclj.results :refer [pass-result fail-result pending-result error-result]]
[speclj.run.standard :refer [run-specs]]
[clojure.test]))

(defmacro with-test-out-str [& body]
`(let [s# (new java.io.StringWriter)]
(binding [clojure.test/*test-out* s#]
~@body
(str s#))))

(describe "Clojure Test Reporter"
(with reporter (new-clojure-test-reporter))
(with a-failure (fail-result (new-characteristic "flips" (new-description "Crazy" "some.ns") "flip") 0.3 (new-failure "Expected flips")))
(with an-error (error-result (new-exception "Compilation failed")))
(around [spec] (binding [clojure.test/*report-counters* (ref clojure.test/*initial-report-counters*)] (spec)))

(it "reports pass"
(with-test-out-str (report-pass @reporter nil))
(should= 1
(:pass @clojure.test/*report-counters*)))

(it "reports pending"
(with-test-out-str (report-pending @reporter nil))
(should= 1
(:pending @clojure.test/*report-counters*)))

(it "reports fail"
(with-test-out-str (report-fail @reporter @a-failure))
(should= 1
(:fail @clojure.test/*report-counters*)))

(it "reports failure message"
(let [lines (str/split-lines (with-test-out-str (report-fail @reporter @a-failure)))]
(should-contain "FAIL in (Crazy flips)" (nth lines 1))
(should-contain "Expected flips" (nth lines 2))))

(it "reports error"
(with-test-out-str (report-error @reporter @an-error))
(should= 1
(:error @clojure.test/*report-counters*)))

(it "reports error message"
(let [lines (str/split-lines (with-test-out-str (report-error @reporter @an-error)))]
(should-contain "ERROR in (unknown)" (nth lines 1))
(should-contain "Compilation failed" (nth lines 2))
(should-contain "actual: java.lang.Exception: Compilation failed" (nth lines 4))))

(it "reports run results"
(with-test-out-str
(report-pending @reporter nil)
(report-pass @reporter nil)
(report-fail @reporter @a-failure)
(report-error @reporter @an-error))
(let [output (with-test-out-str (report-runs @reporter nil))
lines (str/split-lines output)]
(should= 3 (count lines))
(should= "Ran 3 tests containing 3 assertions." (nth lines 1))
(should= "1 failures, 1 errors." (nth lines 2))))
)

(run-specs)
12 changes: 11 additions & 1 deletion src/speclj/config.clj
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,21 @@
(dynamically-invoke (str "speclj.run." name) (str "new-" name "-runner"))
(catch java.lang.Exception e (throw (java.lang.Exception. (str "Failed to load runner: " name) e)))))

(defn load-reporter [name]
(defn- load-reporter-by-name [name]
(try
(dynamically-invoke (str "speclj.report." name) (str "new-" name "-reporter"))
(catch java.lang.Exception e (throw (java.lang.Exception. (str "Failed to load reporter: " name) e)))))

;cljs-ignore->
(defn load-reporter [name-or-object]
(if (instance? (Class/forName "speclj.reporting.Reporter") name-or-object)
name-or-object
(load-reporter-by-name name-or-object)))
;<-cljs-ignore
;cljs-include (defn load-reporter [name-or-object] (load-reporter-by-name name-or-object))



(defn parse-tags [values]
(loop [result {:includes #{} :excludes #{}} values values]
(if (seq values)
Expand Down
78 changes: 78 additions & 0 deletions src/speclj/report/clojure_test.clj
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
(ns speclj.report.clojure-test
(:require [speclj.config :refer [default-reporters]]
[speclj.platform]
[speclj.reporting :refer [tally-time red green yellow grey stack-trace-str indent prefix]]
[speclj.results :refer [pass? fail? pending? categorize]]
[clojure.string :as str]
[clojure.test]
[clojure.string :as string :refer [split]]))

(defn error-message [e] (.getMessage e))

(defn full-name [characteristic]
(loop [context @(.-parent characteristic) name (.-name characteristic)]
(if context
(recur @(.-parent context) (str (.-name context) " " name))
name)))

(def file-separator (System/getProperty "file.separator"))

(defn- classname->filename [classname]
(let [root-name (first (split classname #"\$"))]
(str
(string/replace root-name "." file-separator)
".clj")))

(defn failure-source [failure]
(let [source (nth (.getStackTrace failure) 0)
classname (.getClassName source)
filename (classname->filename classname)]
(if-let [url (.getResource (clojure.lang.RT/baseLoader) filename)]
{:file (.getFile url) :line (.getLineNumber source)}
{:file filename :line (.getLineNumber source)})))

(deftype ClojureTestReporter []
speclj.reporting/Reporter
(report-message [this message]
(println message) (flush))

(report-description [this description])

(report-pass [this result]
(clojure.test/inc-report-counter :test)
(clojure.test/report {:type :pass}))

(report-pending [this result]
(clojure.test/inc-report-counter :test)
(clojure.test/inc-report-counter :pending))

(report-fail [this result]
(clojure.test/inc-report-counter :test)
(let [characteristic (.-characteristic result)
failure (.-failure result)
characteristic-text (full-name characteristic)]
(binding [clojure.test/*testing-vars* [(with-meta {} {:name (symbol characteristic-text)})]]
(clojure.test/report
(merge
{:type :fail}
(failure-source failure)
{:message (error-message failure)
:expected "see above"
:actual "see above"})))))

(report-error [this result]
(let [ex (.-exception result)]
(binding [clojure.test/*testing-vars* [(with-meta {} {:name (symbol "unknown")})]]
(clojure.test/report
(merge
{:type :error}
(failure-source ex)
{:message (.getMessage ex)
:expected "not recorded"
:actual ex})))))

(report-runs [this results]
(clojure.test/report (merge {:type :summary} @clojure.test/*report-counters*))))

(defn new-clojure-test-reporter []
(ClojureTestReporter.))

0 comments on commit 1a55452

Please # to comment.