Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Customizing reporters #69

Merged
merged 2 commits into from
Nov 11, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.))