This repository has been archived by the owner on Nov 9, 2017. It is now read-only.
/
expect.clj
59 lines (56 loc) · 1.74 KB
/
expect.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
(ns lazytest.expect
(:import (lazytest ExpectationFailed)))
(defn- local-bindings
"Returns a map of the names of local bindings to their values."
[env]
(reduce (fn [m sym] (assoc m `'~sym sym))
{} (keys env)))
(defn- function-call?
"True if form is a list representing a normal function call."
[form]
(and (seq? form)
(let [sym (first form)]
(and (symbol? sym)
(let [v (resolve sym)]
(and (var? v)
(bound? v)
(not (:macro (meta v)))
(let [f (var-get v)]
(fn? f))))))))
(defmacro expect
"Evaluates expression. If it returns logical true, returns that
result. If the expression returns logical false, throws
lazytest.ExpectationFailed with an attached map describing the
reason for failure. Metadata on expr and on the 'expect' form
itself will be merged into the failure map."
([expr] `(expect nil ~expr))
([docstring expr]
{:pre [(or (string? docstring) (nil? docstring))]}
(if (function-call? expr)
;; Normal function call
`(let [f# ~(first expr)
args# (list ~@(rest expr))
result# (apply f# args#)]
(or result#
(throw (ExpectationFailed.
(merge '~(meta &form)
'~(meta expr)
{:form '~expr
:locals ~(local-bindings &env)
:evaluated (list* f# args#)
:result result#
:file ~*file*
:ns *ns*}
~(when docstring {:doc docstring}))))))
;; Unknown type of expression
`(let [result# ~expr]
(or result#
(throw (ExpectationFailed.
(merge '~(meta &form)
'~(meta expr)
{:form '~expr
:locals ~(local-bindings &env)
:result result#
:file ~*file*
:ns *ns*}
~(when docstring {:doc docstring})))))))))