[rspec-users] New article on "Listening to Your Specs" up on Ruby Advent 2008
ben at benmabey.com
Tue Dec 16 15:58:35 EST 2008
Lenny Marks wrote:
> On Dec 9, 2008, at 10:40 PM, Avdi Grimm wrote:
>> I contributed an article on BDD and RSpec to the Ruby Advent Calendar
>> 2008, going over some of the rules I've collected for interpreting
>> what your specs say about your design. It can be found here:
> I'm curious where others stand on the topic of object level specs with
> describe blocks named after methods. I posted the comment below with
> my 2 cents.
> I agree with most of the points in this article, but not so much the
> part about:
> Contexts named after methods
> A describe block should encapsulate a particular scenario: an object
> or set of objects in a specific configuration. If objects are nouns,
> and methods are verbs, then contexts should describe nouns, not verbs.
> I think this is more or less what Aslak was saying but I wanted to get
> more specific. IMO, using rspec to spec behavior at the object/unit
> level, it often makes perfect sense to describe the behavior of the
> verbs(methods). I think the following contrived example would be fine.
> It clearly shows me the what this method does and what the scenarios
> it handles are.
> describe Account, "#debit" #maybe 'debiting' is better, but #debit is
> actually more descriptive of the API which is the level I'm at here.
> describe "with sufficient funds"
> it "should reduce balance by debited amount"
> it "should ..."
> describe "with insufficient funds"
> it "should raise an InsufficentFundsError"
> it "should ...
> Actually in the above example I probably would have started with the
> following and only grouped into nested contexts when I started
> repeating myself(e.g. repetition of 'when balance is sufficient')
> describe Account, "#debit"
> it "should reduce balance by debited amount when balance is sufficient"
> it "should raise an InsufficentFundsError when insufficient"
> Examples named after methods
> There is rarely a one-to-one relationship between desired behaviors
> and methods on an object. When you name an example after the method it
> tests, it’s a clue that you have started to think in “implementation
> brain” rather than “behavior brain”. You’re thinking “I know we are
> going to need a method “#foo” which does such-and-so, so I’ll just
> start spec-ing it now…”. Step back, and think about the behavior you
> are really interested in. You may find it changes how you write
> examples. Or, you may find that you didn’t need that method at all.
> I don't agree much with the above either. I think this the difference
> between speccing behavior at the application level vs. object level. I
> don't feel its a smell to get down to the object level when necessary.
> One of the benefits of BDD at the object/code level(as opposed to
> feature level) is helping to flesh out the API(what classes, what
> methods, what inputs/outputs) that implements a feature. New classes
> and methods spring into existence as I realize that there are
> details(a new responsibility) that I eventually want to drill into but
> would only be distracting or messy at the current level. Using object
> level examples to focus in on something in isolation is a valuable
> technique. Again, its all about focussing at the right level of
> For ex. part of an 'update profile' feature might involve showing a
> user an error message if he/she submits invalid data. Now I wouldn't
> start off thinking, I'm going to need a User class with a validate
> method, but going from the outside in might eventually drive me to it
> so that I can drill into all the details of what constitutes valid
> data directly/in isolation, without being mixed in with a bunch of
> other stuff or extra
> rspec-users mailing list
> rspec-users at rubyforge.org
I agree with a lot of what Avdi said in the article. One big exception
was the the "Contexts named after methods" section. (However, I do
agree with the examples named after methods.)
My argument for having contexts named after methods is simple:
documentation. It helps me quickly scan example groups to find specific
examples about how to use the public methods (the API.) Maybe we should
be using rdoc more but the team I work with has adopted this convention
and have found that it helps us understand how to use objects written by
other team members. This convention does not work well with all
examples however, so we use it on a case-by-case basis.
Another reason why I think I like using method names in contexts is
because of how I like to develop. Going from the outside-in I usually
use mocks to discover the interfaces I wish I had. Once I finish
writing the collaborators I then start on the object's implementation.
I start by documenting (writing code examples of) the cases how the
collaborators are already using that method and expecting the object to
behave from using the object in that way... So, I actually find using
method names in example groups a very natural thing to do that just
comes from going outside-in. At least in my experience. :) Again, I
don't stick to this way for organizing all of my examples but I think it
has its place and adds value.
More information about the rspec-users