 (defmacro assertion [locals & body]
   (format-assertion (Assertion locals `(do ~@body))))
 
+(defmacro defassert
+  "Defines an Assertion.
+  decl => docstring? [locals*] body*"
+  [name & decl]
+  (let [m {:name name}
+        m (if (string? (first decl)) (assoc m :doc (first decl)) m)
+        decl (if (string? (first decl)) (next decl) decl)
+        argv (first decl)
+        m (assoc m :locals argv)
+        body (next decl)]
+    (assert (vector? argv))
+    `(def ~name (with-meta (assertion ~argv ~@body)
+                  '~m))))
+
 
 ;;; CONTEXT HANDLING
 

    (assert (= @*log* [:c6-open]))
    (dorun (result-seq results))
    (assert (= @*log* [:c6-open :a3 :a4 :a3 :a4]))))

                                 (reverse (:contexts t))))))
        (TestResult t results))
      (catch Throwable e (TestThrown t e)))))

(defmacro deftest
  "Defines a test case containing assertions that share the same contexts.
  decl => docstring? [binding*] assertion*
  binding => symbol context
  assertion => docstring? expression"
  [name & decl]
  (let [m {:name name}
        m (if (string? (first decl)) (assoc m :doc (first decl)) m)
        decl (if (string? (first decl)) (next decl) decl)
        bindings (first decl)
        assertions (next decl)]
    (assert (vector? bindings))
    (assert (even? (count bindings)))
    (let [locals (vec (map first (partition 2 bindings)))
          contexts (vec (map second (partition 2 bindings)))]
      (assert (every? symbol locals))
      `(def ~name
            (with-meta (TestCase ~contexts
                                 ~(loop [r [], as assertions]
                                    (if (seq as)
                                      (if (string? (first as))
                                        (recur (conj r `(with-meta (assertion ~locals ~(next as))
                                                          {:doc ~(first as)}))
                                               (nnext as))
                                        (recur (conj r `(assertion ~locals ~(first as))) (next as)))
                                      r)))
              '~m)))))

(defmacro defsuite
  "Defines a test suite containing other test cases or suites.
  decl => docstring? [context*] children*"
  [name & decl]
  (let [m {:name name}
        m (if (string? (first decl)) (assoc m :doc (first decl)) m)
        decl (if (string? (first decl)) (next decl) decl)
        contexts (first decl)
        children (next decl)]
    (assert (vector? contexts))
    `(def ~name (with-meta (TestCase ~contexts ~(vec children))
                  '~m))))


;;; TEST RESULT HANDLING

