aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorStuart Sierra <mail@stuartsierra.com>2008-12-17 22:07:23 +0000
committerStuart Sierra <mail@stuartsierra.com>2008-12-17 22:07:23 +0000
commitadbb35189ef5578f57e9b480a3d6ea74ff152060 (patch)
tree415bc72e7b4965a0af5b68b2ad54f7389777f610 /src
parentcc85eef5f2453aa4b7e2e63c88b623c507eaebe7 (diff)
test_is.clj: deftests are functions, tests are composable, source line in failure report
Diffstat (limited to 'src')
-rw-r--r--src/clojure/contrib/test_is.clj49
1 files changed, 37 insertions, 12 deletions
diff --git a/src/clojure/contrib/test_is.clj b/src/clojure/contrib/test_is.clj
index 02adbae8..fcb58029 100644
--- a/src/clojure/contrib/test_is.clj
+++ b/src/clojure/contrib/test_is.clj
@@ -72,7 +72,7 @@
(def *report-counters* nil) ; bound to a ref of a map in test-ns
-(def *test-name* nil) ; bound to the name of a var during testing
+(def *testing-vars* (list)) ; bound to hierarchy of vars being tested
@@ -81,6 +81,15 @@
;; These are used in assert-expr methods. Rebind "report" to plug in
;; your own test-reporting framework.
+(defn testing-str
+ "Returns a string representation of the current test. Renders names
+ in *testing-vars* as a list, then the source file and line of
+ current test."
+ []
+ (str (reverse (map #(:name (meta %)) *testing-vars*))
+ " (" (:file (meta (first *testing-vars*)))
+ ":" (:line (meta (first *testing-vars*))) ")"))
+
(defn report-count
"Increments the named counter in *report-counters*."
[name]
@@ -99,14 +108,14 @@
(defmethod report :fail [event msg expected actual]
(report-count :fail)
- (println "\nFAIL in" *test-name*)
+ (println "\nFAIL in" (testing-str))
(when msg (println msg))
(println "expected:" (pr-str expected))
(println " actual:" (pr-str actual)))
(defmethod report :error [event msg expected actual]
(report-count :error)
- (println "\nERROR in" *test-name*)
+ (println "\nERROR in" (testing-str))
(when msg (println msg))
(println "expected:" (pr-str expected))
(println " actual:" (pr-str actual)))
@@ -215,20 +224,31 @@
;;; DEFINING TESTS INDEPENDENT OF FUNCTIONS
(defmacro deftest
- "Defines a Var with no value and with body in its :test fn."
+ "Defines a test function with no arguments. Test functions may call
+ other tests, so tests may be composed. If you compose tests, you
+ should also define a function named test-ns-hook; run-tests will
+ call this function.
+
+ If name is nil, a symbol like T-123 will be generated.
+
+ Note: Actually, the test body goes in the :test metadata on the var,
+ and the real function (the value of the var) calls test-var on
+ itself."
[name & body]
- `(def ~(with-meta name {:test `(fn [] ~@body)})))
+ (let [symbol (if (nil? name) (gensym "T-") name)]
+ `(def ~(with-meta symbol {:test `(fn [] ~@body)})
+ (fn [] (test-var (var ~symbol))))))
;;; RUNNING TESTS
(defn test-var
- "If v has a function in its :test metadata, calls that function, with
- *test-name* bound to the name of the var."
+ "If v has a function in its :test metadata, calls that function,
+ with *testing-vars* bound to (conj *testing-vars* v)."
[v]
(when-let [t (:test (meta v))]
- (binding [*test-name* (str v)]
+ (binding [*testing-vars* (conj *testing-vars* v)]
(report-count :test)
(try (t)
(catch Throwable e
@@ -236,15 +256,20 @@
nil e))))))
(defn test-ns
- "Tests all vars in the namespace. Returns a map of counts
- for :test, :pass, :fail, and :error results."
+ "If the namespace defines a function named test-ns-hook, calls that.
+ Otherwise, calls test-var on all vars in the namespace. Returns a
+ map of counts for :test, :pass, :fail, and :error results."
[ns]
(binding [*report-counters* (ref {:test 0, :pass 0,
:fail 0, :error 0})]
(let [ns (if (symbol? ns) (find-ns ns) ns)]
(report :info (str "Testing " ns) nil nil)
- (doseq [v (vals (ns-interns ns))]
- (test-var v)))
+ ;; If ns has a test-ns-hook function, call that:
+ (if-let [v (find-var (symbol (str (ns-name ns)) "test-ns-hook"))]
+ ((var-get v))
+ ;; Otherwise, just test every var in the ns.
+ (doseq [v (vals (ns-interns ns))]
+ (test-var v))))
@*report-counters*))
(defn print-results