diff options
Diffstat (limited to 'src/clojure/contrib/test_is/test_is.clj')
-rw-r--r-- | src/clojure/contrib/test_is/test_is.clj | 238 |
1 files changed, 0 insertions, 238 deletions
diff --git a/src/clojure/contrib/test_is/test_is.clj b/src/clojure/contrib/test_is/test_is.clj deleted file mode 100644 index 14d9c6b3..00000000 --- a/src/clojure/contrib/test_is/test_is.clj +++ /dev/null @@ -1,238 +0,0 @@ -;;; test_is.clj: test framework for Clojure - -;; by Stuart Sierra, http://stuartsierra.com/ -;; September 25, 2008 - -;; Thanks to Chas Emerick for contributions. -;; Thanks to Allen Rohner for assert-raises. - -;; Copyright (c) 2008 Stuart Sierra. All rights reserved. The use and -;; distribution terms for this software are covered by the Common -;; Public License 1.0 (http://www.opensource.org/licenses/cpl1.0.php) -;; which can be found in the file CPL.TXT at the root of this -;; distribution. By using this software in any fashion, you are -;; agreeing to be bound by the terms of this license. You must not -;; remove this notice, or any other, from this software. - - - -;; Inspired by many Common Lisp test frameworks and clojure/test, this -;; file is a Clojure test framework. -;; -;; Define tests as :test metadata on your fns. Use the "is" macro -;; for assertions. Examples: -;; -;; (defn add2 -;; ([x] (+ x 2)) -;; {:test (fn [] (is (= (add2 3) 5)) -;; (is (= (add2 -4) -2) -;; (is (> (add2 50) 50)))}) -;; -;; You can also define tests in isolation with the "deftest" macro: -;; -;; (deftest test-new-fn -;; (is (= (new-fn) "Awesome"))) -;; -;; You can test that a function throws an exception with the "throws" -;; macro: -;; -;; (defn factorial -;; ([n] (cond -;; (zero? n) 1 ; 0!=1 is often defined for convenience -;; (> n 0) (* n (factorial (dec n))) -;; :else (throw (IllegalArgumentException. "Negative factorial")))) -;; {:test (fn [] (is (= (factorial 3) 6)) -;; (is (= (factorial 6) 720)) -;; (throws IllegalArgumentException (factorial -2)))}) -;; -;; Run tests with (run-tests). As in any language with macros, you may -;; need to recompile functions after changing a macro definition. - - -(ns clojure.contrib.test-is) - -(def - #^{:doc "PrintWriter to which test results are printed; defaults to - System.err."} - *test-out* (. System err)) - - -;;; PRIVATE - -(defmacro #^{:private true} defcounter [ref-name fn-name] - `(do (def ~(with-meta ref-name {:private true}) nil) - (defn ~fn-name [] - (when ~ref-name (sync nil (commute ~ref-name inc)))))) - -(defcounter *tests* count-test) -(defcounter *assertions* count-assertion) -(defcounter *failures* count-failure) -(defcounter *exceptions* count-exception) - -(defmacro failure [reason message] - `(throw (new java.lang.AssertionError - (str ~reason (when ~message (str "; " ~message)))))) - -(defn- assert-true [form message] - `(do (count-assertion) - (let [value# ~form] - (when-not value# - (failure (str ~(pr-str form) " was false/nil") - ~message))))) - -;; Multimethod for testing expressions, dispatches on the first symbol -;; in the expression. -(defmulti assert-expr (fn [form message] (first form))) - -;; Test for (= actual expected) expressions. -(defmethod assert-expr '= [form message] - (let [expr1 (second form) - expr2 (nth form 2)] - `(do (count-assertion) - (let [value1# ~expr1 - value2# ~expr2] - (when-not (= value1# value2#) - (failure (str ~(pr-str expr1) " is " (pr-str value1#) - " but should be " (pr-str value2#)) - ~message)))))) - -;; Test for (instance? class object) expressions. -(defmethod assert-expr 'instance? [form message] - (let [clazz (second form) - object (nth form 2)] - `(do (count-assertion) - (let [value1# ~clazz - value2# ~object] - (when-not (instance? value1# value2#) - (failure (str ~(pr-str object) " has " (class value2#) - " but should have " (pr-str value1#)) - ~message)))))) - -;; Generic expression test, just check if expression evaluates to -;; logical true. -(defmethod assert-expr :default [form message] - (assert-true form message)) - -(defn- always-fail-assert [message] - `(do (count-assertion) - (failure ~message nil))) - -(defmacro #^{:private true} with-test-counters - "Creates dynamic bindings for counting the number of tests, - assertions, failures, and exceptions. Returns the results in a - map." - [& body] - `(binding [*tests* (ref 0) - *assertions* (ref 0) - *failures* (ref 0) - *exceptions* (ref 0)] - ~@body - {:tests @*tests* - :assertions @*assertions* - :failures @*failures* - :exceptions @*exceptions*})) - -(defn- run-test-fn - "Calls the function; reports errors/exceptions." - [f name] - (try - (count-test) - (f) - (catch java.lang.AssertionError e - (count-failure) - (. *test-out* (println (str "FAIL in " name ": " - (.getMessage e))))) - (catch java.lang.Exception e - (count-exception) - (. *test-out* (println (str "EXCEPTION in " name ":"))) - (.printStackTrace e *test-out*)))) - -(defn- test-var - "Finds and calls the fn in a var's :test metadata." - [v] - (when-let f (:test (meta v)) - (run-test-fn f (str v)))) - -(defn- test-interns - "Tests all interned symbols in the namespace." - [ns] - (let [ns (if (symbol? ns) (find-ns ns) ns)] - (. *test-out* (println (str "Testing " ns))) - (dorun (map test-var (vals (ns-interns ns)))))) - - -;;; PUBLIC - -(defmacro is - "Generic assertion macro. Throws AssertionError if form evaluates - logical false. Optional message will be added to the error. - - form may be one of: - * an equality test like (= expression expected-value) - * an instance? test like (instance? class expression) - * nil, which always fails - * an arbitrary expression, fails if it returns false/nil" - ([form] `(is ~form nil)) - ([form message] - (cond - (nil? form) (always-fail-assert message) - (seq? form) (assert-expr form message) - :else (assert-true form message)))) - -(defmacro throws - "Asserts that form throws an exception of the given class (or one of - its subclasses)." - ([class form] - `(throws ~class ~form nil)) - ([class form message] - `(try - (count-assertion) - (let [value# ~form] - (failure (str "expected " ~(pr-str form) " to throw " ~class - ", but returned " value#) ~message)) - (catch ~class e# nil) ; the correct exception was thrown - (catch java.lang.Throwable e# ; some other exception was thrown - (failure (str "expected " ~(pr-str form) " to throw " ~class - ", but threw " e#) ~message))))) - -(defn print-results - "Prints a summary of the results from test-ns to *test-out*." - [r] - (. *test-out* - (println (str "\nRan " (:tests r) " tests with " - (:assertions r) " assertions.\n" - (:failures r) " failures, " - (:exceptions r) " exceptions."))) ) - -(defn test-ns - "Runs tests on all interned symbols in the namespaces - (symbols or namespace objects). - - Returns a map with the following keys: - :tests => number of tests run - :assertions => number of assertions checked - :failures => number of failed assertions - :exceptions => number of exceptions raised - - If no namespace is given, uses *ns*." - ([] (test-ns *ns*)) - ([& namespaces] - (with-test-counters (dorun (map test-interns namespaces))))) - -(defn run-tests - "Runs tests in the given namespaces and prints a summary of - results. - - If no namespace is given, uses *ns*." - [& namespaces] - (print-results (apply test-ns namespaces))) - -(defn run-all-tests - "Runs tests in all namespaces and prints a summary of results." - [] - (apply run-tests (all-ns))) - -(defmacro deftest - "Defines a Var with no value and with body in its :test fn." - [name & body] - `(def ~(with-meta name {:test `(fn [] ~@body)}))) |