Merge f632d74d9f into 238a98d9b2
This commit is contained in:
commit
d1b238be0f
3 changed files with 78 additions and 31 deletions
|
|
@ -1,6 +1,7 @@
|
||||||
(ns babashka.impl.clojure.stacktrace
|
(ns babashka.impl.clojure.stacktrace
|
||||||
{:no-doc true}
|
{:no-doc true}
|
||||||
(:require [clojure.stacktrace :as stacktrace]
|
(:require [clojure.stacktrace :as stacktrace]
|
||||||
|
[clojure.string :as str]
|
||||||
[sci.core :as sci]))
|
[sci.core :as sci]))
|
||||||
|
|
||||||
(def sns (sci/create-ns 'clojure.stacktrace nil))
|
(def sns (sci/create-ns 'clojure.stacktrace nil))
|
||||||
|
|
@ -13,9 +14,62 @@
|
||||||
(defn new-var [var-sym f]
|
(defn new-var [var-sym f]
|
||||||
(sci/new-var var-sym f {:ns sns}))
|
(sci/new-var var-sym f {:ns sns}))
|
||||||
|
|
||||||
|
(defn right-pad [s n]
|
||||||
|
(let [n (- n (count s))]
|
||||||
|
(str s (str/join (repeat n " ")))))
|
||||||
|
|
||||||
|
(defn format-stacktrace [st]
|
||||||
|
(let [st (force st)
|
||||||
|
data (keep (fn [{:keys [:file :ns :line :column :sci/built-in
|
||||||
|
:local]
|
||||||
|
nom :name}]
|
||||||
|
(when (or line built-in)
|
||||||
|
{:name (str (if nom
|
||||||
|
(str ns "/" nom)
|
||||||
|
ns)
|
||||||
|
(when local
|
||||||
|
(str "#" local)))
|
||||||
|
:loc (str (or file
|
||||||
|
(if built-in
|
||||||
|
"<built-in>"
|
||||||
|
"<expr>"))
|
||||||
|
(when line
|
||||||
|
(str ":" line ":" column)))}))
|
||||||
|
st)
|
||||||
|
max-name (reduce max 0 (map (comp count :name) data))]
|
||||||
|
(mapv (fn [{:keys [:name :loc]}]
|
||||||
|
(str (right-pad name max-name) " - " loc))
|
||||||
|
data)))
|
||||||
|
|
||||||
|
(defn print-throwable
|
||||||
|
[^Throwable tr]
|
||||||
|
(when tr
|
||||||
|
(printf "%s: %s" (.getName (class tr)) (.getMessage tr))
|
||||||
|
(when-let [info (ex-data tr)]
|
||||||
|
(newline)
|
||||||
|
(pr info))))
|
||||||
|
|
||||||
|
(defn print-stack-trace [e]
|
||||||
|
(print-throwable (.getCause e))
|
||||||
|
(newline)
|
||||||
|
(->> e
|
||||||
|
(sci/stacktrace)
|
||||||
|
(format-stacktrace)
|
||||||
|
(run! println)))
|
||||||
|
|
||||||
|
(defn print-cause-trace
|
||||||
|
([tr] (print-cause-trace tr nil))
|
||||||
|
([^Throwable tr n]
|
||||||
|
(print-stack-trace tr)
|
||||||
|
(when-let [cause (.getCause tr)]
|
||||||
|
(print "Caused by: ")
|
||||||
|
(recur cause n))))
|
||||||
|
|
||||||
(def stacktrace-namespace
|
(def stacktrace-namespace
|
||||||
{'root-cause (sci/copy-var stacktrace/root-cause sns)
|
{'root-cause (sci/copy-var stacktrace/root-cause sns)
|
||||||
'print-trace-element (new-var 'print-trace-element (wrap-out stacktrace/print-trace-element))
|
'print-trace-element (new-var 'print-trace-element (wrap-out stacktrace/print-trace-element))
|
||||||
'print-throwable (new-var 'print-throwable (wrap-out stacktrace/print-throwable))
|
'print-throwable (new-var 'print-throwable (wrap-out stacktrace/print-throwable))
|
||||||
|
;; FIXME: expose print-stack-trace as well
|
||||||
'print-stack-trace (new-var 'print-stack-trace (wrap-out stacktrace/print-stack-trace))
|
'print-stack-trace (new-var 'print-stack-trace (wrap-out stacktrace/print-stack-trace))
|
||||||
'print-cause-trace (new-var 'print-cause-trace (wrap-out stacktrace/print-cause-trace))})
|
;; FIXME: should we make both regular and sci-aware stack printers available?
|
||||||
|
'print-cause-trace (new-var 'print-cause-trace (wrap-out print-cause-trace))})
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,9 @@
|
||||||
;; contributions and suggestions.
|
;; contributions and suggestions.
|
||||||
|
|
||||||
(ns
|
(ns
|
||||||
^{:author "Stuart Sierra, with contributions and suggestions by
|
^{:author "Stuart Sierra, with contributions and suggestions by
|
||||||
Chas Emerick, Allen Rohner, and Stuart Halloway",
|
Chas Emerick, Allen Rohner, and Stuart Halloway",
|
||||||
:doc "A unit testing framework.
|
:doc "A unit testing framework.
|
||||||
|
|
||||||
ASSERTIONS
|
ASSERTIONS
|
||||||
|
|
||||||
|
|
@ -231,10 +231,10 @@
|
||||||
|
|
||||||
For additional event types, see the examples in the code.
|
For additional event types, see the examples in the code.
|
||||||
"}
|
"}
|
||||||
babashka.impl.clojure.test
|
babashka.impl.clojure.test
|
||||||
(:require
|
(:require
|
||||||
[babashka.impl.common :refer [ctx]]
|
[babashka.impl.common :refer [ctx]]
|
||||||
[clojure.stacktrace :as stack]
|
[babashka.impl.clojure.stacktrace :as bbstack]
|
||||||
[clojure.template :as temp]
|
[clojure.template :as temp]
|
||||||
[sci.core :as sci]
|
[sci.core :as sci]
|
||||||
[sci.impl.namespaces :as sci-namespaces]
|
[sci.impl.namespaces :as sci-namespaces]
|
||||||
|
|
@ -248,10 +248,10 @@
|
||||||
;;; USER-MODIFIABLE GLOBALS
|
;;; USER-MODIFIABLE GLOBALS
|
||||||
|
|
||||||
(defonce
|
(defonce
|
||||||
^{:doc "True by default. If set to false, no test functions will
|
^{:doc "True by default. If set to false, no test functions will
|
||||||
be created by deftest, set-test, or with-test. Use this to omit
|
be created by deftest, set-test, or with-test. Use this to omit
|
||||||
tests when compiling or loading production code."}
|
tests when compiling or loading production code."}
|
||||||
load-tests
|
load-tests
|
||||||
(sci/new-dynamic-var '*load-tests* true {:ns tns}))
|
(sci/new-dynamic-var '*load-tests* true {:ns tns}))
|
||||||
|
|
||||||
(def
|
(def
|
||||||
|
|
@ -261,7 +261,6 @@
|
||||||
stack-trace-depth
|
stack-trace-depth
|
||||||
(sci/new-dynamic-var '*stack-trace-depth* nil {:ns tns}))
|
(sci/new-dynamic-var '*stack-trace-depth* nil {:ns tns}))
|
||||||
|
|
||||||
|
|
||||||
;;; GLOBALS USED BY THE REPORTING FUNCTIONS
|
;;; GLOBALS USED BY THE REPORTING FUNCTIONS
|
||||||
|
|
||||||
(def report-counters (sci/new-dynamic-var '*report-counters* nil {:ns tns})) ; bound to a ref of a map in test-ns
|
(def report-counters (sci/new-dynamic-var '*report-counters* nil {:ns tns})) ; bound to a ref of a map in test-ns
|
||||||
|
|
@ -342,7 +341,7 @@
|
||||||
[m]
|
[m]
|
||||||
(report
|
(report
|
||||||
(case
|
(case
|
||||||
(:type m)
|
(:type m)
|
||||||
:fail m
|
:fail m
|
||||||
:error m
|
:error m
|
||||||
m)))
|
m)))
|
||||||
|
|
@ -372,7 +371,7 @@
|
||||||
(print " actual: ")
|
(print " actual: ")
|
||||||
(let [actual (:actual m)]
|
(let [actual (:actual m)]
|
||||||
(if (instance? Throwable actual)
|
(if (instance? Throwable actual)
|
||||||
(stack/print-cause-trace actual @stack-trace-depth)
|
(bbstack/print-cause-trace actual @stack-trace-depth)
|
||||||
(prn actual)))))
|
(prn actual)))))
|
||||||
|
|
||||||
(defmethod report-impl :summary [m]
|
(defmethod report-impl :summary [m]
|
||||||
|
|
@ -390,8 +389,6 @@
|
||||||
(defmethod report-impl :begin-test-var [m])
|
(defmethod report-impl :begin-test-var [m])
|
||||||
(defmethod report-impl :end-test-var [m])
|
(defmethod report-impl :end-test-var [m])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;; UTILITIES FOR ASSERTIONS
|
;;; UTILITIES FOR ASSERTIONS
|
||||||
|
|
||||||
(defn get-possibly-unbound-var
|
(defn get-possibly-unbound-var
|
||||||
|
|
@ -453,8 +450,6 @@
|
||||||
:expected '~form, :actual value#}))
|
:expected '~form, :actual value#}))
|
||||||
value#))
|
value#))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;; ASSERTION METHODS
|
;;; ASSERTION METHODS
|
||||||
|
|
||||||
;; You don't call these, but you can add methods to extend the 'is'
|
;; You don't call these, but you can add methods to extend the 'is'
|
||||||
|
|
@ -530,21 +525,18 @@
|
||||||
:expected '~form, :actual e#})))
|
:expected '~form, :actual e#})))
|
||||||
e#))))
|
e#))))
|
||||||
|
|
||||||
|
|
||||||
(defmacro try-expr
|
(defmacro try-expr
|
||||||
"Used by the 'is' macro to catch unexpected exceptions.
|
"Used by the 'is' macro to catch unexpected exceptions.
|
||||||
You don't call this."
|
You don't call this."
|
||||||
{:added "1.1"}
|
{:added "1.1"}
|
||||||
[msg form]
|
[msg form]
|
||||||
`(try ~(assert-expr msg form)
|
`(try ~(assert-expr msg form)
|
||||||
(catch Throwable t#
|
(catch ~(with-meta 'Exception {:sci/error true}) t#
|
||||||
(clojure.test/do-report {:file clojure.core/*file*
|
(clojure.test/do-report {:file clojure.core/*file*
|
||||||
:line ~(:line (meta form))
|
:line ~(:line (meta form))
|
||||||
:type :error, :message ~msg,
|
:type :error, :message ~msg,
|
||||||
:expected '~form, :actual t#}))))
|
:expected '~form, :actual t#}))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;; ASSERTION MACROS
|
;;; ASSERTION MACROS
|
||||||
|
|
||||||
;; You use these in your tests.
|
;; You use these in your tests.
|
||||||
|
|
@ -602,8 +594,6 @@
|
||||||
`(binding [clojure.test/*testing-contexts* (conj clojure.test/*testing-contexts* ~string)]
|
`(binding [clojure.test/*testing-contexts* (conj clojure.test/*testing-contexts* ~string)]
|
||||||
~@body))
|
~@body))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;; DEFINING TESTS
|
;;; DEFINING TESTS
|
||||||
|
|
||||||
(defmacro with-test
|
(defmacro with-test
|
||||||
|
|
@ -618,7 +608,6 @@
|
||||||
`(doto ~definition (alter-meta! assoc :test (fn [] ~@body)))
|
`(doto ~definition (alter-meta! assoc :test (fn [] ~@body)))
|
||||||
definition))
|
definition))
|
||||||
|
|
||||||
|
|
||||||
(defmacro deftest
|
(defmacro deftest
|
||||||
"Defines a test function with no arguments. Test functions may call
|
"Defines a test function with no arguments. Test functions may call
|
||||||
other tests, so tests may be composed. If you compose tests, you
|
other tests, so tests may be composed. If you compose tests, you
|
||||||
|
|
@ -644,7 +633,6 @@
|
||||||
`(def ~(vary-meta name assoc :test `(fn [] ~@body) :private true)
|
`(def ~(vary-meta name assoc :test `(fn [] ~@body) :private true)
|
||||||
(fn [] (test-var (var ~name))))))
|
(fn [] (test-var (var ~name))))))
|
||||||
|
|
||||||
|
|
||||||
(defmacro set-test
|
(defmacro set-test
|
||||||
"Experimental.
|
"Experimental.
|
||||||
Sets :test metadata of the named var to a fn with the given body.
|
Sets :test metadata of the named var to a fn with the given body.
|
||||||
|
|
@ -656,8 +644,6 @@
|
||||||
(when @load-tests
|
(when @load-tests
|
||||||
`(alter-meta! (var ~name) assoc :test (fn [] ~@body))))
|
`(alter-meta! (var ~name) assoc :test (fn [] ~@body))))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;; DEFINING FIXTURES
|
;;; DEFINING FIXTURES
|
||||||
|
|
||||||
(defn- add-ns-meta
|
(defn- add-ns-meta
|
||||||
|
|
@ -700,9 +686,6 @@
|
||||||
[fixtures]
|
[fixtures]
|
||||||
(reduce compose-fixtures default-fixture fixtures))
|
(reduce compose-fixtures default-fixture fixtures))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;; RUNNING TESTS: LOW-LEVEL FUNCTIONS
|
;;; RUNNING TESTS: LOW-LEVEL FUNCTIONS
|
||||||
|
|
||||||
(defn test-var-impl
|
(defn test-var-impl
|
||||||
|
|
@ -766,8 +749,6 @@
|
||||||
(do-report {:type :end-test-ns, :ns ns-obj}))
|
(do-report {:type :end-test-ns, :ns ns-obj}))
|
||||||
@@report-counters))
|
@@report-counters))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;; RUNNING TESTS: HIGH-LEVEL FUNCTIONS
|
;;; RUNNING TESTS: HIGH-LEVEL FUNCTIONS
|
||||||
|
|
||||||
(defn run-tests
|
(defn run-tests
|
||||||
|
|
|
||||||
|
|
@ -122,6 +122,18 @@ true")))))
|
||||||
|
|
||||||
(deftest testing-vars-str-test
|
(deftest testing-vars-str-test
|
||||||
(is (str/includes?
|
(is (str/includes?
|
||||||
(bb "(clojure.test/testing-vars-str {:file \"x\" :line 1})")
|
(bb "(clojure.test/testing-vars-str {:file \"x\" :line 1})")
|
||||||
"() (x:1)")
|
"() (x:1)")
|
||||||
"includes explicit line number + file name in test report"))
|
"includes explicit line number + file name in test report"))
|
||||||
|
|
||||||
|
(deftest is-should-include-name-of-function-test
|
||||||
|
(let [output (bb "(require '[clojure.test :as t]) (defn function-under-test [] (zero? nil)) (t/deftest foo (t/is (= false (function-under-test)))) (foo)")]
|
||||||
|
(is (str/includes? output "user/function-under-test"))))
|
||||||
|
|
||||||
|
(deftest is-should-throw-wrapped-exception-assert-test
|
||||||
|
(let [output (bb "(require '[clojure.test :as t]) (t/deftest foo (t/is (assert false))) (foo)")]
|
||||||
|
;; FIXME: doesn't work for assert yet
|
||||||
|
#_(is (str/includes? output ":type :sci/error"))))
|
||||||
|
|
||||||
|
;; FIXME: handle thrown?
|
||||||
|
;; FIXME: handle thrown-with-message?
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue