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

Reply via email to