I don't get rspec

> I do have a bone to pick with the tutorial (or maybe I don't understand
> TDD/BDD yet). In the stack example, I cringe with horror when I see them
> setting a method that just returns "true" simply to get a test to pass.
> That grates on me, because I *know* I'm actually going to have to write
> the real code eventually. It seems like a waste of time to do the
> nitty-gritty "add a test to the spec/add a trivial fix to the code" cycle.
>
The idea behind doing small steps is that you know exactly what went wrong
when you run the tests. If you roll several steps into one test/development
cycle then you have many possibilities to investigate what went wrong if
they fail.

Sometimes, it is easier to skip the most trivial steps though!

Also keep in mind that is just a tutorial example. The goal is just to
communicate the process - spec first, make the spec pass, next step.
It's all about a single point of failure, and a clear mapping between
specs and functionality.

···

--
Giles Bowkett

Blog: http://gilesbowkett.blogspot.com
Portfolio: http://www.gilesgoatboy.org

It keeps them in the right set of mind: "How should objects in some
contexts behave?" and not "what equality/difference/basic property/...
should I test?".

Each context in rSpec is just a new testcase. For example,
EmptyStackTest's setup() can be written "@stack = Stack.new",
FullStackTest's steup() can be written "@stack = Stack.new;
@stack.fillup...."

so a rSpec file with 5 contexts is same as 5 unit testcase files,
although I almost always only write one testcase per class. if
assert_equal is ambiguous, you always can use assert(object.attr [== |
equal | eql] "expected")

From my point of view, same testing tasks done in rSpec is not much

easier than using existing tools (Test/unit, rails testing tools).

Yes. This has always bothered me about the zentest tool. I love many of the tools in that package, but the zentest tool seems to encourage bad testing habits. The video linked to earlier in the thread explains why.

James Edward Gray II

···

On Jan 19, 2007, at 6:55 PM, Sam Smoot wrote:

The problem is a lot of people don't do TDD right, and the semantics of
it raise the barrier to entry.

It is worth noting that rSpec is not the only player in the field of behavior testing. It simply goes a bit further providing the whole framework in place of Test/Unit (it reads much better, for one). I use Mocha with Test/Unit for behavior/unit testing an is quite happy with the combo. I saw it mentioned somewhere that Mocha comes by default in RoR installations, so they have means for behavior testing already ;-).

Gennady.

···

-----Original Message-----
From: Sam Smoot [mailto:ssmoot@gmail.com]
Sent: Fri 1/19/2007 16:55
To: ruby-talk ML
Subject: Re: I don't get rspec

nicknameoptional wrote:

besides more English like, how is it better than the assert_equal?

It's not. If you're doing TDD right, then BDD is just what you're doing
already, by another name.

The problem is a lot of people don't do TDD right, and the semantics of
it raise the barrier to entry.

BDD is about trying to change those semantics, so TDD
As-It-Was-Meant-To-Be becomes more popular. It's just a bonus that
rSpec reads so nicely and prints out nice looking reports.

So I was in the same boat as you. Then I decided: "You know, they have
a point about people misinterpreting TDD. So is trying to change the
language used to describe it really such an awful thing?"

And that's where I am now.

Is using rSpec in your projects going to increase velocity by 10%? Or
make it easier to communicate with business people? Or allow you to
write better tests? Have fewer bugs? Any of these things? No. Not if
you're already doing TDD well. It might help more developers to get
there though. It might help new team-members integrate faster with less
training on TDD and the way you're doing things. It might just give you
a warm fuzzy. Compared to a lot of the arbitrary and complex choices we
sometimes make, you could do a lot worse I think.

Giles Bowkett wrote:

I saw Dave Astels talk about this, at Canada on Rails, and initially I
thought it was a bunch of BS. It seemed like the only difference
between BDD and TDD was the words; everything else was just the same
thing with new names.

It's easy for folk to dismiss RSpec by saying that it's just semantics
... but when you are dealing with meaning, semantics is everything.

TDD isn't really about testing -- it's
about design. BDD makes it easier to use TDD for what it's really for.

Heh, you nailed it!

···

--
-- Jim Weirich

--
Posted via http://www.ruby-forum.com/\.

Joel VanderWerf <vjoel@path.berkeley.edu> writes:

> I like the continuity with test/unit. I'd be more likely to use this
> than rspec for my older projects.
>
> Questions (from a BDD newbie):
>
> Are the context and specify argument strings purely documentation, or
> do they need to be class or method names?

They can contain anything except NUL bytes (the extended symbol
syntax). They are turned into class and method names automatically
(we need some special formatting for that due to Test::Unit
restrictions).

> Is it possible to nest contexts? Is this a good idea?

test/spec allows them since 0.2, and I use them to group contexts that
go together. Note that nothing is inherited, it's purely namespacing.
RSpec doesn't have them, and they aren't interesting in implementing
them AFAICT.

That's correct. We've really struggled with this because users want a
means of sharing context material, but we believe that nesting
contexts is going to lead to specs that are confusing to look at. We
believe that clarity supercedes DRY in specs, and so we haven't
supported this yet.

That said, you can include modules and get reuse that way:

module SomeHelperMethodsUsefulAcrossContexts
end

context "some context" do
  include SomeHelperMethodsUsefulAcrossContexts
end

I'd be surprised if test/spec doesn't already support this out of the box.

Cheers,
David

···

On 1/23/07, Christian Neukirchen <chneukirchen@gmail.com> wrote:

> Inside of a context, is there a setup/teardown protocol as there is in
> test/unit?

Yes, you can use

    context "Blah" do
      setup do
        @blah = Blah.new
      end

      teardown do
        @blah.destroy!
      end
    end

You can have multiple of these, and they are run in order of
appearance.

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

Wayne Vucenic wrote:
> I don't look at this as "add a test to the spec/add a trivial fix to
> the code" but instead as "add a test to the spec/do the simplest thing
> that could possibly work to get the tests to pass", and I find
> substantial value in this approach.

When I do TDD, I approach it with a Jeckle and Hyde perspective. When I
write a test, I am writing a specification of how the code should work.

When I start writing code, I become the laziest programmer you can
imagine, writing only enough code to pass the specification as it is
written at that moment. If it is not called out in the spec, it doesn't
get written.

When I switch back to test writing, I cuss out that lazy programmer
(i.e. me just a few moments ago) and write additional specs to force the
code to do exactly what I want.

The tension between Dr. Jeckle (the spec writer), and Mr. Hyde (the
programmer) causes Dr. Jeckle to write better specs and Mr. Hyde to
write lean, correct code.

With me it's more like Abbott and Costello!

Seriously, thanks for describing this so well.

Cheers,
David

···

On 1/23/07, Jim Weirich <jim@weirichhouse.org> wrote:

--
-- Jim Weirich

--
Posted via http://www.ruby-forum.com/\.

Actually I believe that the pure process of
test-driven/behavior-driven development is:

1) Write the test/spec
2) Ensure that it FAILS
3) Write the code to make it pass
4) Goto step 1

Step 2 is to debug the spec.

···

On 6/25/07, Giles Bowkett <gilesb@gmail.com> wrote:

Also keep in mind that is just a tutorial example. The goal is just to
communicate the process - spec first, make the spec pass, next step.
It's all about a single point of failure, and a clear mapping between
specs and functionality.

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

Is there an equivalent to autotest for rspec (autospec?)? I've googled
around, but only came across a Rails plugin, which (perhaps obviously)
is very Rails-centric.

-P

···

On 1/23/07, David Chelimsky <dchelimsky@gmail.com> wrote:

On 1/23/07, Christian Neukirchen <chneukirchen@gmail.com> wrote:
> Joel VanderWerf <vjoel@path.berkeley.edu> writes:
>
> > I like the continuity with test/unit. I'd be more likely to use this
> > than rspec for my older projects.
> >
> > Questions (from a BDD newbie):
> >
> > Are the context and specify argument strings purely documentation, or
> > do they need to be class or method names?
>
> They can contain anything except NUL bytes (the extended symbol
> syntax). They are turned into class and method names automatically
> (we need some special formatting for that due to Test::Unit
> restrictions).
>
> > Is it possible to nest contexts? Is this a good idea?
>
> test/spec allows them since 0.2, and I use them to group contexts that
> go together. Note that nothing is inherited, it's purely namespacing.
> RSpec doesn't have them, and they aren't interesting in implementing
> them AFAICT.

That's correct. We've really struggled with this because users want a
means of sharing context material, but we believe that nesting
contexts is going to lead to specs that are confusing to look at. We
believe that clarity supercedes DRY in specs, and so we haven't
supported this yet.

That said, you can include modules and get reuse that way:

module SomeHelperMethodsUsefulAcrossContexts
end

context "some context" do
  include SomeHelperMethodsUsefulAcrossContexts
end

I'd be surprised if test/spec doesn't already support this out of the box.

Cheers,
David

>
> > Inside of a context, is there a setup/teardown protocol as there is in
> > test/unit?
>
> Yes, you can use
>
> context "Blah" do
> setup do
> @blah = Blah.new
> end
>
> teardown do
> @blah.destroy!
> end
> end
>
> You can have multiple of these, and they are run in order of
> appearance.
>
> --
> Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org
>

What's wrong with zentest, specifically?

Thanks,
Joe

···

On 1/19/07, James Edward Gray II <james@grayproductions.net> wrote:

On Jan 19, 2007, at 6:55 PM, Sam Smoot wrote:

> The problem is a lot of people don't do TDD right, and the
> semantics of
> it raise the barrier to entry.

Yes. This has always bothered me about the zentest tool. I love
many of the tools in that package, but the zentest tool seems to
encourage bad testing habits. The video linked to earlier in the
thread explains why.

"David Chelimsky" <dchelimsky@gmail.com> writes:

That said, you can include modules and get reuse that way:

module SomeHelperMethodsUsefulAcrossContexts
end

context "some context" do
include SomeHelperMethodsUsefulAcrossContexts
end

I'd be surprised if test/spec doesn't already support this out of the box.

It works exactly the same in test/spec.

···

Cheers,
David

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

> Also keep in mind that is just a tutorial example. The goal is just to
> communicate the process - spec first, make the spec pass, next step.
> It's all about a single point of failure, and a clear mapping between
> specs and functionality.

Actually I believe that the pure process of
test-driven/behavior-driven development is:

1) Write the test/spec
2) Ensure that it FAILS
3) Write the code to make it pass
4) Goto step 1

Step 2 is to debug the spec.

The reason that we want to see the test fail is so that we can
confident that when it passes that it's passing because of the code we
wrote in step 3. Otherwise, we could write code that the test doesn't
interact with in any way resulting in a useless test and dead code.

Is that what you mean by "debug the spec?" If not, can you please explain?

Thx,
David

···

On 6/27/07, Rick DeNatale <rick.denatale@gmail.com> wrote:

On 6/25/07, Giles Bowkett <gilesb@gmail.com> wrote:

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

You will probably understand better by watching the movie, but zentest encourages you to make a test case for each class and a test method for each method. BDD teaches that these decisions are pretty arbitrary.

The true goal of testing is to test the "behaviors" of your object. If that means interacting with five methods or just one possible call sequence of a method that has several, that's what you should really be testing. What do if you need to work with two classes at one to test something?

This class and method organization is also encourages you to use so-so names for your tests at best. If you have a Calendar class and a TestCalendar, that's pretty much saying the same thing twice (a violation of DRY) and it doesn't tell you much. BDD encourages you to actually express what you are testing with your naming. This really helps you focus on the goal of the process and is much less arbitrary.

There you have it, in my own words. Just to be clear, the above is my opinion through and through. I do not speak for the zentest or BDD teams.

James Edward Gray II

···

On Jan 23, 2007, at 6:10 PM, Joe Van Dyk wrote:

On 1/19/07, James Edward Gray II <james@grayproductions.net> wrote:

On Jan 19, 2007, at 6:55 PM, Sam Smoot wrote:

> The problem is a lot of people don't do TDD right, and the
> semantics of
> it raise the barrier to entry.

Yes. This has always bothered me about the zentest tool. I love
many of the tools in that package, but the zentest tool seems to
encourage bad testing habits. The video linked to earlier in the
thread explains why.

What's wrong with zentest, specifically?

"David Chelimsky" <dchelimsky@gmail.com> writes:

> That said, you can include modules and get reuse that way:
>
> module SomeHelperMethodsUsefulAcrossContexts
> end
>
> context "some context" do
> include SomeHelperMethodsUsefulAcrossContexts
> end
>
> I'd be surprised if test/spec doesn't already support this out of the box.

It works exactly the same in test/spec.

Glad to hear it. Do you have any feeling about which approach to reuse
you personally prefer? Nested contexts or included modules?

···

On 1/24/07, Christian Neukirchen <chneukirchen@gmail.com> wrote:

> Cheers,
> David
--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

Better late than never. Yes

···

On 6/27/07, David Chelimsky <dchelimsky@gmail.com> wrote:

On 6/27/07, Rick DeNatale <rick.denatale@gmail.com> wrote:
> On 6/25/07, Giles Bowkett <gilesb@gmail.com> wrote:
>
> > Also keep in mind that is just a tutorial example. The goal is just to
> > communicate the process - spec first, make the spec pass, next step.
> > It's all about a single point of failure, and a clear mapping between
> > specs and functionality.
>
> Actually I believe that the pure process of
> test-driven/behavior-driven development is:
>
> 1) Write the test/spec
> 2) Ensure that it FAILS
> 3) Write the code to make it pass
> 4) Goto step 1
>
> Step 2 is to debug the spec.

The reason that we want to see the test fail is so that we can
confident that when it passes that it's passing because of the code we
wrote in step 3. Otherwise, we could write code that the test doesn't
interact with in any way resulting in a useless test and dead code.

Is that what you mean by "debug the spec?" If not, can you please explain?

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

What's wrong with zentest, specifically?

You will probably understand better by watching the movie, but zentest encourages you to make a test case for each class and a test method for each method.

Which will match up 1:1 if you factor your code well.

BDD teaches that these decisions are pretty arbitrary.

I don't use BDD because I already have my tests broken up by units of behavior. I call them methods.

BDD presents a method of thinking about test design to help you focus on better object design and object modeling. Unit testing doesn't have this method of thinking built-in, you have to discover it. (Although it makes itself evident if you pay attention to how difficult it is to test something.)

The true goal of testing is to test the "behaviors" of your object. If that means interacting with five methods or just one possible call sequence of a method that has several, that's what you should really be testing.

I think there are two true goals of testing. One is to enumerate your edge cases so each one behaves as you expect. Another is to get feedback about how well you've designed your program. Both are equally important.

If you want to write specifications to enumerate your edge cases, great. However, if you've factored poorly neither BDD nor TDD will give you small, concise tests nor a small, concise implementation.

What do if you need to work with two classes at one to test something?

Then your classes are probably coupled too tightly.

This class and method organization is also encourages you to use so-so names for your tests at best. If you have a Calendar class and a TestCalendar, that's pretty much saying the same thing twice (a violation of DRY) and it doesn't tell you much. BDD encourages you to actually express what you are testing with your naming. This really helps you focus on the goal of the process and is much less arbitrary.

Mapping tests to classes 1:1 is a sign of proper design. Your implementation's names should reflect the behavior implemented within. If you have to give different names to your tests and your implementation you've probably named your implementation poorly. Instead you should refactor your implementation so that it can be named well.

Read the tutorial on the rspec site:

http://rspec.rubyforge.org/tutorials/index.html

The specifications match up with the implementation very well, so the Stack is probably well-designed. If they didn't, that's a good sign of code smell.

(You get the same code smell out of unit testing, it just smells a little different.)

···

On Jan 23, 2007, at 16:26, James Edward Gray II wrote:

On Jan 23, 2007, at 6:10 PM, Joe Van Dyk wrote:

--
Eric Hodel - drbrain@segment7.net - http://blog.segment7.net

I LIT YOUR GEM ON FIRE!

"David Chelimsky" <dchelimsky@gmail.com> writes:

···

On 1/24/07, Christian Neukirchen <chneukirchen@gmail.com> wrote:

"David Chelimsky" <dchelimsky@gmail.com> writes:

> That said, you can include modules and get reuse that way:
>
> module SomeHelperMethodsUsefulAcrossContexts
> end
>
> context "some context" do
> include SomeHelperMethodsUsefulAcrossContexts
> end
>
> I'd be surprised if test/spec doesn't already support this out of the box.

It works exactly the same in test/spec.

Glad to hear it. Do you have any feeling about which approach to reuse
you personally prefer? Nested contexts or included modules?

As said, nesting is purely for organizational and namespacing purposes.
I use modules.

--
Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org

> "David Chelimsky" <dchelimsky@gmail.com> writes:
>
> > That said, you can include modules and get reuse that way:
> >
> > module SomeHelperMethodsUsefulAcrossContexts
> > end
> >
> > context "some context" do
> > include SomeHelperMethodsUsefulAcrossContexts
> > end
> >
> > I'd be surprised if test/spec doesn't already support this out of the box.
>
> It works exactly the same in test/spec.

Glad to hear it. Do you have any feeling about which approach to reuse
you personally prefer? Nested contexts or included modules?

I know I'm not the person that this was targeted at, but I would absolutely
love to see nested contexts included in rspec... I was just wishing I could
do that yesterday.

···

On Wed, 24 Jan 2007 22:05:17 +0900 "David Chelimsky" <dchelimsky@gmail.com> wrote:

On 1/24/07, Christian Neukirchen <chneukirchen@gmail.com> wrote:

>
> > Cheers,
> > David
> --
> Christian Neukirchen <chneukirchen@gmail.com> http://chneukirchen.org
>
>

--
Luke Ivers <technodolt@gmail.com>

> >
> > > Also keep in mind that is just a tutorial example. The goal is just to
> > > communicate the process - spec first, make the spec pass, next step.
> > > It's all about a single point of failure, and a clear mapping between
> > > specs and functionality.
> >
> > Actually I believe that the pure process of
> > test-driven/behavior-driven development is:
> >
> > 1) Write the test/spec
> > 2) Ensure that it FAILS
> > 3) Write the code to make it pass
> > 4) Goto step 1
> >
> > Step 2 is to debug the spec.
>
> The reason that we want to see the test fail is so that we can
> confident that when it passes that it's passing because of the code we
> wrote in step 3. Otherwise, we could write code that the test doesn't
> interact with in any way resulting in a useless test and dead code.
>
> Is that what you mean by "debug the spec?" If not, can you please explain?

Better late than never. Yes

:slight_smile:

Thanks

···

On 7/18/07, Rick DeNatale <rick.denatale@gmail.com> wrote:

On 6/27/07, David Chelimsky <dchelimsky@gmail.com> wrote:
> On 6/27/07, Rick DeNatale <rick.denatale@gmail.com> wrote:
> > On 6/25/07, Giles Bowkett <gilesb@gmail.com> wrote:

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

>> What's wrong with zentest, specifically?
>
> You will probably understand better by watching the movie, but
> zentest encourages you to make a test case for each class and a
> test method for each method.

Which will match up 1:1 if you factor your code well.

The point is that you shouldn't try to shoehorn your tests into this
1:1 approach. You brought up the tutorial as an example of specs that
match up nicely with the code, but even that ends up with a few
contexts. If you just have a StackTest class, you won't get the same
logical separation. How many programmers are going to write an
EmpyStackTest class, a OneItemStackTest class, a FullStackTest class,
etc?

As your behavior becomes more complex - by interacting with other
objects - you need to be able to drill a bit deeper with your
specifications. I often have one complete context for an individual
method. Not many programmers will create a new test class just to
spec a method. And that doesn't mean that this method is too tightly
coupled to other objects, it just means that you need more
finely-grained specifications.

BDD presents a method of thinking about test design to help you focus
on better object design and object modeling. Unit testing doesn't
have this method of thinking built-in, you have to discover it.

The bottom line is that if you're using either Test::Unit or RSpec the
most effectively, you're probably doing things nearly the same way
that you would with the other framework. The difference is that RSpec
guides you to the proper way. Unit testing doesn't have the proper
thinking built-in, as you said. The BDD guys give us a testing tool
with some of the lessons they've learned over the years built-in.
It's just a different path to the same place.

Pat

···

On 1/23/07, Eric Hodel <drbrain@segment7.net> wrote:

On Jan 23, 2007, at 16:26, James Edward Gray II wrote:
> On Jan 23, 2007, at 6:10 PM, Joe Van Dyk wrote: