-
Notifications
You must be signed in to change notification settings - Fork 21
/
clj_test.clj
97 lines (90 loc) · 3.92 KB
/
clj_test.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
(ns matcher-combinators.clj-test
(:require [matcher-combinators.core :as core]
[matcher-combinators.printer :as printer]
[matcher-combinators.parser]
[matcher-combinators.result :as result]
[clojure.string :as str]
[clojure.test :as clojure.test]))
(defn- stacktrace-file-and-line
[stacktrace]
(if (seq stacktrace)
(let [^StackTraceElement s (first stacktrace)]
{:file (.getFileName s) :line (.getLineNumber s)})
{:file nil :line nil}))
(defn- core-or-this-class-name? [^StackTraceElement stacktrace]
(let [cl-name (.getClassName stacktrace)]
(or (str/starts-with? cl-name "matcher_combinators.test$")
(str/starts-with? cl-name "java.lang."))))
;; had to include this from `clojure.test` because there is no good way to run
;; this logic when not reporting a `:fail` or `:error`.
(defn with-file+line-info [report]
(->> (.getStackTrace (Thread/currentThread))
(drop-while core-or-this-class-name?)
stacktrace-file-and-line
(merge report)))
(defmethod clojure.test/assert-expr 'match? [msg form]
`(let [[matcher# actual#] (list ~@(rest form))]
(if (core/matcher? matcher#)
(let [result# (core/match matcher# actual#)]
(clojure.test/do-report
(if (core/match? result#)
{:type :pass
:message ~msg
:expected '~form
:actual (list 'match? matcher# actual#)}
(with-file+line-info
{:type :matcher-combinators/mismatch
:message ~msg
:expected '~form
:actual (list '~'not (list 'match? matcher# actual#))
:markup (::result/value result#)}))))
(clojure.test/do-report
{:type :fail
:message ~msg
:expected '~form
:actual (str "The first argument of match? isn't a matcher")}))))
(defmethod clojure.test/assert-expr 'thrown-match? [msg form]
;; (is (thrown-with-match? exception-class matcher expr))
;; Asserts that evaluating expr throws an exception of class c.
;; Also asserts that the exception data satisfies the provided matcher.
(let [klass (nth form 1)
matcher (nth form 2)
body (nthnext form 3)]
`(try ~@body
(clojure.test/do-report {:type :fail, :message ~msg, :expected '~form, :actual nil})
(catch ~klass e#
(let [result# (core/match ~matcher (ex-data e#))]
(clojure.test/do-report
(if (core/match? result#)
{:type :pass
:message ~msg
:expected '~form
:actual (list 'thrown-match? ~klass ~matcher '~body)}
(with-file+line-info
{:type :matcher-combinators/exception-mismatch
:message ~msg
:expected '~form
:actual (list '~'not (list 'thrown-match? ~klass ~matcher '~body))
:ex-class ~klass
:markup (::result/value result#)}))))
e#))))
(defmethod clojure.test/report :matcher-combinators/exception-mismatch [m]
(clojure.test/with-test-out
(clojure.test/inc-report-counter :fail)
(println "\nFAIL in" (clojure.test/testing-vars-str m))
(when (seq clojure.test/*testing-contexts*)
(println (clojure.test/testing-contexts-str)))
(when-let [message (:message m)]
(println message))
(println (:ex-class m) "data mismatches:")
(printer/pretty-print (:markup m))))
(defmethod clojure.test/report :matcher-combinators/mismatch [m]
(clojure.test/with-test-out
(clojure.test/inc-report-counter :fail)
(println "\nFAIL in" (clojure.test/testing-vars-str m))
(when (seq clojure.test/*testing-contexts*)
(println (clojure.test/testing-contexts-str)))
(when-let [message (:message m)]
(println message))
(println "mismatch:")
(printer/pretty-print (:markup m))))