             (catch Throwable t#
               (AssertionThrown '~form t#))))))
  
-(defn compile-assertion [a]
+(defn compile-assertion
+  "Compiles an Assertion a into a function of its locals."
+  [a]
   (eval (format-assertion a)))
  
-(defmacro assertion [locals & body]
+(defmacro assertion
+  "Returns a compiled Assertion function like (fn [locals] body)."
+  [locals & body]
   (format-assertion (Assertion locals (if (= 1 (count body))
                                         (first body) `(do ~@body)))))
 

  [r]
  (tree-seq :children :children r))

(require 'clojure.stacktrace)

(defn result-identifier [r]
  (let [m (meta (:source r))]
    (or (:name m) (:form m)


(ns #^{:doc "Lazy Testing Framework"
       :author "Stuart Sierra"}
  com.stuartsierra.lazytest
  (:require clojure.stacktrace))

;;; PROTOCOLS

;; Generic reporting function for any Test/Assertion Result
(defprotocol TestSuccess
  (success? [r] "Returns true if r is a 100% successful result."))

;; Generic entry-point for running tests.
(defprotocol Testable
  (run-tests [x] "Runs tests defined for the Namespace, Var, or TestCase."))

;; Internal generic Test/Assertion invocation.
(defprotocol TestInvokable
  (invoke-test [t states strategy active]
               "(private) Executes the TestCase or Assertion."))

;; Fn is assumed to be a compiled Assertion
(extend-class clojure.lang.Fn TestInvokable
              (invoke-test [f states strategy active] (apply f states)))

