Last active
November 27, 2024 12:50
-
-
Save PEZ/5f1101ee69ccedf042c3bea5116a8cd0 to your computer and use it in GitHub Desktop.
Baldr, clojure.test and cljs/test with Mocha-inspired positive reporting
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns pez.baldr | |
(:require #?(:cljs [cljs.test :as t] | |
:clj [clojure.test :as t]) | |
[clojure.string :as string])) | |
(defn- default [text] | |
(str "\033[39m" text "\033[22m")) | |
(defn- gray [text] | |
(str "\033[90m" text "\033[39m")) | |
(defn- green [text] | |
(str "\033[1;32m" text "\033[22m")) | |
(defn- red [text] | |
(str "\033[31m" text "\033[39m")) | |
(def ^:private initial-state {:contexts nil | |
:failure-prints []}) | |
(defonce ^:private !state (atom initial-state)) | |
(defn- indent [level] | |
(apply str (repeat (* 2 level) " "))) | |
(defn- get-report [m contexts state {:keys [color bullet bullet-color]}] | |
(let [seen-contexts (:contexts state) | |
common-contexts (take-while true? (map = (reverse seen-contexts) (reverse contexts))) | |
common-prefix-length (count common-contexts) | |
new-contexts (reverse (take (- (count contexts) common-prefix-length) contexts)) | |
message (or (:message m) (pr-str (:expected m)))] | |
{:new-state (assoc state :contexts contexts) | |
:printouts (cond-> [] | |
(seq new-contexts) (into (map-indexed (fn [idx ctx] | |
(str (indent (+ common-prefix-length idx 2)) | |
(default ctx))) | |
new-contexts)) | |
:always (conj (str (indent (+ 2 (count contexts))) | |
(str (bullet-color bullet) " " (color message)))))})) | |
(defn report! [m config] | |
(let [contexts #?(:cljs (:testing-contexts (t/get-current-env)) | |
:clj t/*testing-contexts*) | |
{:keys [new-state printouts]} (get-report m contexts @!state config)] | |
(reset! !state new-state) | |
(doseq [printout printouts] | |
(println printout)))) | |
(defn- dispatch-value [type] | |
#?(:clj type | |
:cljs [::t/default type])) | |
(defmethod t/report (dispatch-value :begin-test-var) [_m] | |
(swap! !state merge (select-keys initial-state [:contexts]))) | |
(def ^:private original-summary (get-method t/report (dispatch-value :summary))) | |
(defmethod t/report (dispatch-value :summary) [m] | |
(when (seq (:failure-prints @!state)) | |
(println)) | |
(doseq [[i failure-print] (map-indexed vector (:failure-prints @!state))] | |
(println (red (str (inc i) ") " (string/trim failure-print))))) | |
(reset! !state initial-state) | |
(original-summary m)) | |
(def ^:private original-pass (get-method t/report (dispatch-value :pass))) | |
(defmethod t/report (dispatch-value :pass) [m] | |
(report! m {:color gray | |
:bullet "β" | |
:bullet-color green}) | |
(original-pass m)) | |
(def ^:private original-fail (get-method t/report (dispatch-value :fail))) | |
(defmethod t/report (dispatch-value :fail) [m] | |
(let [failure-printout (with-out-str (original-fail m))] | |
(swap! !state update :failure-prints conj failure-printout)) | |
(report! m {:color red | |
:bullet (str (count (:failure-prints @!state)) ")") | |
:bullet-color red})) | |
(def ^:private original-error (get-method t/report (dispatch-value :error))) | |
(defmethod t/report (dispatch-value :error) [m] | |
(let [error-printout (with-out-str (original-error m))] | |
(swap! !state update :failure-prints conj error-printout)) | |
(report! m {:color red | |
:bullet (str (count (:failure-prints @!state)) ")") | |
:bullet-color red})) | |
(defmethod t/report (dispatch-value :begin-test-var) [m] | |
(println (str (indent 1) (default (:var m))))) |
Update: Now I understand why I didn't succeed with making it .cljc
at first. It wasn't totally obvious. But now Baldr works in both Clojure and ClojureScript. π
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It's not really done yet, but it mostly seems to work. Looks like so:
Where the headers are the
(testing "...")
messages, and the bullets either theis
message or, lacking a message, the expected clause from theis
form.Like Mocha, it will collect failures and errors, indexing them, and report them last, as part of the summary:
I tried to make it a
.cljc
module, because there's nothing ClojureScript specific about it, but I didn't get it to work. I think that to use it with Clojure, just replace all references tocljs.test
.My use case for this does not have any async tests, so probably this reporting won't work with async tests?
I may make a library out of this, if that is of interest for anyone.
Feedback welcome! I am probably doing it all wrong. π