Oops, ignore the part about extracting the parameter name from the fn form. I meant to delete that part, I misunderstood your problem at first.
I say just use functions - you don't need macros here. The boilerplate of typing "(fn [client] " multiple times is not enough to justify their use, IMO. Jeff On May 28, 2:04 pm, jweiss <jeffrey.m.we...@gmail.com> wrote: > On May 27, 1:46 pm, nil <ache...@gmail.com> wrote: > > > > > > > > > > > I was looking > > athttp://saucelabs.com/blog/index.php/2009/12/running-your-selenium-tes... > > and in the comments, :Scott suggested that a macro could reduce some > > of the boilerplate that you see here: > > > (def test-google > > { > > :name "google" > > :test (fn [client] > > (doto client > > (.open "http://www.google.com") > > (.type "q" "Sauce Labs") > > (.click "btnG") > > (.waitForPageToLoad "5000")) > > (.isTextPresent client "Selenium"))}) > > > (def test-yahoo > > { > > :name "yahoo" > > :test (fn [client] > > (doto client > > (.open "http://yahoo.com") > > (.type "p" "Sauce Labs") > > (.click "search-submit") > > (.waitForPageToLoad "5000")) > > (.isTextPresent client "Selenium"))}) > > > You can see the boilerplate of defining the map, typing the names of > > the two keys, calling the thing "test-<name>" ... So I tried writing a > > macro for this. But when I use my first attempt, it says Can't use > > qualified name as parameter. Here's my first attempt: > > > (defmacro deftest [name & body] > > (let [test-n (symbol (str "test-" name)) > > n (str name)] > > `(def ~test-n > > {:name ~n > > :test (fn [client] > > ~@body)}))) > > > The macro expansion of the following looks good, but actually running > > it yields the complaint mentioned above: > > > (deftest google > > (doto client > > (.open "http://www.google.com") > > (.type "q" "Sauce Labs") > > (.click "btnG") > > (.waitForPageToLoad "5000")) > > (.isTextPresent client "Selenium")) > > > My second attempt works ...... > > > (defmacro deftest [name client & body] > > (let [test-n (symbol (str "test-" name)) > > n (str name)] > > `(def ~test-n > > {:name ~n > > :test (fn [~client] > > ~@body)}))) > > > ... but now the user has to mention the client twice: > > > (deftest google client > > (doto client > > (.open "http://www.google.com") > > (.type "q" "Sauce Labs") > > (.click "btnG") > > (.waitForPageToLoad "5000")) > > (.isTextPresent client "Selenium")) > > > How do I get around this? > > I think what others are getting at is that you shouldn't have the > macro define the 'frame' of the (fn ...) form. Just pass it in whole > in your macro call like > > (deftest google > (fn [client] > (doto client > (.open "http://www.google.com") > (.type "q" "Sauce Labs") > (.click "btnG") > (.waitForPageToLoad "5000")) > (.isTextPresent client "Selenium"))) > > It is a bit more boilerplate but you're less likely to shoot yourself > in the foot. One thing i've done in macros, (and I don't know how > advisable or "good clojure" this is), but, *if* you're sure all your > (fn...) forms you pass in will be explicit fn forms, and not just the > symbol of an existing function, you can extract the parameter name and > use it as your "name" field. > > In the macro you'd do something like (-> (second body) first name), > which would return the string "client". > It's probably not the best idea since it *would* prevent you from > passing in symbols of existing functions, rather than (fn ...) > forms. > > I'm not sure if you really require vars defined for each test, or if > you can just put them in a single map like so: > > (def tests {:google (fn [client] ...) > :yahoo (fn [client] ...)}) > > and then it'd be easy to process that map: > > (defn generate [m] > (zipmap (keys m) (for [[k v] m] {:name (name k) :test v}))) > > and finally > > (run-tests (generate tests)) > > HTH, > Jeff -- 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 Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en