-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Ah, I get it. This works really well!

(defn mock-page-fixture [f]
  (binding [load-page (fn [name] ...)]
    (f)))

This approach feels very functional indeed, I'm going to use it. It's
not really the same as my original TDD inspired design, because that
would allow me to easily write additional providers - but why bother if
I don't read it right now?

On 10/24/2010 09:29 PM, Stuart Sierra wrote:
> In clojure.test, you can use the Clojure `binding` macro to provide
> local replacements for global functions.
> 
> In Lazytest, you can use the context objects provided by
> lazytest.context.stub.
> 
> -S
> 
> 
> On Oct 24, 3:03 pm, "Felix H. Dahlke" <f...@ubercode.de> wrote:
> Hi Stuart,
> 
> I just read through this thread again and noticed that I didn't notice
> you mentioning that I can stub functions within tests. I had a look at
> the clojure.test documentation, but I didn't find an example of that.
> 
> How would that apply to my case? Would I still have to pass a function
> in? (One wouldn't be enough actually, I have several load functions by now.)
> 
> Whether I'll do TDD or not, I decided that I definitely need unit tests.
> 
> On 10/12/2010 06:59 PM, Stuart Sierra wrote:
> 
> 
> 
> 
> 
>>>> Datatypes that implement a single method can be more simply
>>>> represented as ordinary functions, e.g.
> 
>>>> (defn real-provider ...)
>>>> (defn fake-provider ...)
> 
>>>> (defn load-page [provider ...]
>>>>   (let [foo (provider)]
>>>>   ...))
> 
>>>> That being said, you have other options: In clojure.test you can using
>>>> `binding` to stub out functions within your tests. Lazytest <http://
>>>> github.com/stuartsierra/lazytest> has explicit support for stubbing
>>>> out functions during testing.
> 
>>>> -S
> 
>>>> On Oct 11, 6:06 pm, "Felix H. Dahlke" <f...@ubercode.de> wrote:
>>>>> Hi,
> 
>>>>> I'm new to Clojure, using it for a reasonably sized project for the
>>>>> first time, and I'm trying to do test-driven development.
> 
>>>>> While it does work well technically  - clojure.test is very nice to use
>>>>> and feels a lot like JUnit 4's assertThat() - I'm wondering if I'm
>>>>> trying to program Java in Clojure.
> 
>>>>> Here's an example:
> 
>>>>> I'm writing a class (Um. I mean, a ... namespace? Well, a horde of
>>>>> functions.) that accesses web pages from a backend, which can e.g. take
>>>>> these from the filesystem or from a database. In Java or C++, I'd use an
>>>>> interface for that and create one implementation for the filesystem and
>>>>> one for the database:
> 
>>>>> interface Provider {
>>>>>     String loadPage(String name);
> 
>>>>> }
> 
>>>>> This is possible in Clojure:
> 
>>>>> (defprotocol Provider
>>>>>   (load-page [this name])
> 
>>>>> It can be implemented using deftype:
> 
>>>>> (deftype DatabaseProvider []
>>>>>   Provider
>>>>>   (load-page [this name]
>>>>>     (have-fun-with-the-database)))
> 
>>>>> And I can call it like this:
> 
>>>>> (load-page (DatabaseProvider.) "foo")
> 
>>>>> Feels a little weird (especially since all examples of defprotocol and
>>>>> deftype use camel case for type names), but works.
> 
>>>>> Back to my question: Am I trying to do Java in Clojure? Is there a more
>>>>> Lisp-y way to do this?
> 
>>>>> As you may have suspected, this design wasn't my initial intention, it
>>>>> was driven by TDD: This allows me to create a mock implementation
>>>>> against which I can write my test cases without having having to depend
>>>>> on external resources. Typical TDD design. In fact, there will only be
>>>>> one backend for now.
> 
>>>>> This made me wonder if test-driven development was desirable in Clojure
>>>>> at all, or even in functional programming in general.
> 
>>>>> There's a few articles on the issue. Many seem to be from Clojure
>>>>> newcomers, asking questions themselves, and none handles design issues
>>>>> like mock objects [1].
> 
>>>>> One guy basically said that he stopped doing TDD because the REPL makes
>>>>> it possible to test specific functions directly [2]. I can see how he
>>>>> says that the *driven* aspect of TDD can be performed by the REPL, but I
>>>>> find it too inconvenient for extensive use.
> 
>>>>> Bob Martin says that, because functional programming differs from
>>>>> object-oriented programming (In my opinion, these paradigms are
>>>>> compatible - did he mean imperative programming?), test-driven
>>>>> development has to start by testing the details, and work up to testing
>>>>> the big picture. TDD in e.g. Java starts with the big picture and moves
>>>>> down. I don't understand his points completely, but if he's right, this
>>>>> might be a fundamental problem for TDD in functional languages.
> 
>>>>> One guy partly disagrees with him on some matters, but doesn't really
>>>>> mention the bottom-up thing [4].
> 
>>>>> What are your thoughts on these issues? Is anybody here doing TDD in
>>>>> Clojure? Is anybody against it?
> 
>>>>> [1]:http://www.magpiebrain.com/2010/02/16/struggling-with-test-driven-clo...
>>>>> [2]:http://s-expressions.com/2009/07/28/clojure-the-repl-and-test-driven-...
>>>>> [3]:http://blog.objectmentor.com/articles/2010/06/03/tdd-in-clojure
>>>>> [4]:http://ericlefevre.net/wordpress/2010/06/04/bob-martin-on-tdd-in-cloj...
> 
>>>>>  signature.asc
>>>>> < 1KViewDownload
> 
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkzF+M0ACgkQJc3crOgfbuapLgCePKePknmXH25GRHNwsaf/rgSA
KkgAn2w/XofaPbm2DgQTm30mChDS1vJi
=o2yk
-----END PGP SIGNATURE-----

-- 
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