I've been working on a small library to assert that functions are called during a unit test.
The syntax looks like: (calls [[user/foo :times 2 :returns 3] [user/bar :returns 42]] (fn-being-tested)) This will assert that foo is called exactly twice, and bar is called exactly once inside the block. I plan to add support for asserting that the functions are called with the right arguments. Comments appreciated, especially about my use of macros, and the syntax. (ns clojure.contrib.expectation (:require [clojure.contrib.test-is :as test])) (defstruct expectation-hash :called :failed :times) (defn expect-obj [[var & args]] (let [opts (apply hash-map args) state (ref (struct-map expectation-hash :name var :called 0 :failed [] :times (get args :times 1)))] {:fn (fn [& _] (dosync (alter state assoc :called (inc (@state :called)))) (opts :returns)) :state state})) (defn- validate-expectation "checks that the expectation was met. Returns true on success" [expt] (let [expected-calls (@(expt :state) :times) actual-calls (@(expt :state) :called)] (if (= expected-calls actual-calls) (do (test/is true (str (@(expt :state) :name) "was called correctly")) true) (test/failure (@(expt :state) :name) (str " expected " expected- calls " actually called " actual-calls " times"))))) (defmacro calls [args & body] "creates a stub function and asserts the fn was called the correct number of times (calls [[user/foo :times 2 :returns 42] [user/bar :times 1 :returns 3]] (user/foo x y z) (user/bar z)" (let [quote-name (fn [sym] `(var ~sym)) get-name (fn [expt] (first expt)) names (into [] (map (comp quote-name get-name) args))] `(let [expect-opts# (map rest ~args) expectations# (map (fn [name# arglist#] (expect-obj (cons name# arglist#))) ~names expect-opts#) fns# (map :fn expectations#) thread-bindings# (apply hash-map (interleave ~names fns#))] (. clojure.lang.Var (pushThreadBindings thread-bindings#)) (try [EMAIL PROTECTED] (finally (. clojure.lang.Var (popThreadBindings)))) (every? validate-expectation expectations#)))) --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---