On Dec 16, 2008, at 3:58 PM, Ben Mabey wrote:
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:
http://advent2008.hackruby.com/past/2008/12/10/
listening_to_your_specs/
--
Avdi
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.
-lenny
I agree with most of the points in this article, but not so much
the part about:
<quote>
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.
</quote>
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"
..
<quote>
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.
</quote>
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
granularity.
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
setup._______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users
Hey Lenny,
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.
-Ben
Actually, I got lost in the semantics a bit. I didn't realize his
'Examples named after methods' anti-example was specify
"#flush_and_reset" not 'describe'. Anyway, I too was mainly having a
problem with 'Contexts named after methods' being identified as a
smell for much the same reasons as you site.
Thanks to you and Dave for your responses. I've commented on the
original article with back links to this thread. Hope I didn't
overstep by saying "I think there is some consensus that 'Contexts
named after methods' is not a smell and can even be a natural result
of 'Outside In' coding".
-lenny
_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users
_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users