I don't get rspec

I just discovered rspec today, reading the example and tutorials,
besides the doc and coverage features, I can’t see how is it different
from unit test. For my rails app, existing testing tools in rails
already fills all my testing needs. So what does rspec do more than
existing testing tools? Thanks.

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

nicknameoptional wrote:

I just discovered rspec today, reading the example and tutorials,
besides the doc and coverage features, I can’t see how is it different
from unit test. For my rails app, existing testing tools in rails
already fills all my testing needs. So what does rspec do more than
existing testing tools? Thanks.

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

There is a good Google video about rspec and Behavior Driven
Development by the very well-dressed Dave A.:

http://video.google.com/videoplay?docid=8135690990081075324&pl=true


James B.

“A language that doesn’t affect the way you think about programming is
not worth knowing.”

  • A. Perlis

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.

nicknameoptional wrote the following on 20.01.2007 01:20 :

I still fail to see the value added by rSpec. In the video, one main

assert_equal is ambiguous and as said in the video, many mismatch the
parameters (I’ve done it several times myself).
@object.method.should_equal is less prone to errors.

This specific comment aside, from what I understood from the video the
main benefit is that it helps those who don’t really get the test
process with TDD not being confused by the naming used in Test::Unit. 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?”. This single change of context doesn’t seem so helpful
at first glance, but in practice I’ve seen numerous developers
(including myself) being drowned in tests, adding new useless or
unimportant ones because they lost focus on what they should test:
correct behaviour of the application and its components. So I believe
this approach can help (“the language shapes the thought” as mentioned
in the video is probably true from my point of view).

A good point is that it definitely enhances test readibility too.

Lionel.

There is a good Google video about rspec and Behavior Driven
Development by the very well-dressed Dave A.:

http://video.google.com/videoplay?docid=8135690990081075324&pl=true


James B.

I still fail to see the value added by rSpec. In the video, one main
point I got was BDD try to break the 1-1 relation of class and test
class, which he said is useful if refactoring code. but writing rails
app, with convention over configuration ideology, I don’t really do
that much refactoring.

and if you look at the example,
@stack.should_be_empty” is mapped to stack.empty? method,
@stack.top.should_equal “one item” is stack.top == “one item”

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

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

On Jan 19, 2007, at 6:55 PM, Sam S. 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.

James Edward G. II

nicknameoptional wrote:

I just discovered rspec today, reading the example and tutorials,
besides the doc and coverage features, I can’t see how is it different
from unit test. For my rails app, existing testing tools in rails
already fills all my testing needs. So what does rspec do more than
existing testing tools? Thanks.

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

Well … I don’t “get” Test::Unit. It just seems so complicated and
intricate. Rspec is a whole lot simpler to use, and it integrates some
good tools, like Rcov. I think it’s the perfect way to learn TDD/BDD.

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.

Part of that may be the algorithm I’m implementing. It’s very well
defined already – not something I have to “figure out” given a set of
behaviors. But the same is true of a stack, which is the example in the
tutorial. Everybody knows what a stack is supposed to do, everybody
knows what the output from sorting an array of strings is supposed to
be, etc. I think a better example would be something where you didn’t
“instantly” know what the code should look like – a case where you
really had some behavior but no code when you started developent, and
had to “create” the objects and methods and classes from the behavior.


M. Edward (Ed) Borasky, FBG, AB, PTA, PGS, MS, MNLP, NST, ACMC§
http://borasky-research.blogspot.com/

If God had meant for carrots to be eaten cooked, He would have given
rabbits fire.

M. Edward (Ed) Borasky wrote:

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.

It seems to be part of Kent Beck’s definition of TDD. AFAICT, he excuses
it away as, “well, this bogus ‘true’ method will be fixed when we get to
the refactor stage – duplication between the ‘true’ in the code and the
‘true’ in the test,” but I don’t really buy that.

Not all of the cases of cheating are going to be duplication – say,
you’re supposed to be implementing the gamma function, but, starting off
only testing natural numbers, you just implement fac first. AFAIK,
implementing factorial is not going to help you implement gamma.
Likewise, saying ‘def size; 0 end’ may make you feel better, but it’s
hardly progress towards an actual implementation of #size.

In any case, if the point is to keep the cycles short and to encourage
the tests to be written, I’d at least like to inject a bit of
pragmatism. We all get interrupted, have short memories, etc. – at the
very least, the stub implementation should be:
def empty?
true # XXX bogus code – actual implementation pending tests
end

(Remember, imaginary folks who are the audience of this rant: Bad code
should look bad.)

Fondly,
Devin

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.

On 1/19/07, M. Edward (Ed) Borasky removed_email_address@domain.invalid wrote:

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.

First of all, it’s just a simple example for people brand new to
RSpec. It’s good to take baby steps. As you do it more you’ll
obviously combine a couple steps into one. But if you get stuck you
can always take a few steps back and then do the baby steps.

Now for the more important theoretical point…

There are two key parts when doing TDD/BDD. The first is writing a
spec that fails. The second is getting it passing. I do that every
single time, no matter how trivial the code is. After you’ve been
doing BDD for a while you’ll probably write a spec and then write the
code, run the spec, and move on. That’ll work really well for you for
a long time. Then one day you’re going to do that and your spec will
pass, but some part of the behavior still doesn’t seem right. You
spend a lot of time hunting this bug down, and finally you get
frustrated and tear out the new code to start from square one. And
you run your spec…and it’s green. What the hell? You just yanked
out your code. Then you realize that you wrote the wrong spec, and
vow never to skip that trivial red step again.

Pat

On 1/20/07, Devin M. removed_email_address@domain.invalid wrote:

the refactor stage – duplication between the ‘true’ in the code and the
‘true’ in the test," but I don’t really buy that.

Not all of the cases of cheating are going to be duplication – say,
you’re supposed to be implementing the gamma function, but, starting off
only testing natural numbers, you just implement fac first. AFAIK,
implementing factorial is not going to help you implement gamma.
Likewise, saying ‘def size; 0 end’ may make you feel better, but it’s
hardly progress towards an actual implementation of #size.

There’s a point that Kent makes I’m not seeing in your description.
Hard coding the return value gets you right to a green bar, which is a
very important part of refactoring. As you refactor towards the real
implementation, the passing tests are an invariant that helps you to
know that you’re not doing things that adversely affect not only the
method that you are working on, but everything else that you’ve
already written.

The value of this is difficult to see in the trivial examples we see
in books, but as an application grows it becomes increasingly
important.

In any case, if the point is to keep the cycles short and to encourage
the tests to be written, I’d at least like to inject a bit of
pragmatism. We all get interrupted, have short memories, etc. – at the
very least, the stub implementation should be:
def empty?
true # XXX bogus code – actual implementation pending tests
end

If that helps you to feel more confidence so that you can progress,
then do it. That’s an important point of TDD. To provide YOU with
confidence that you’re doing the right thing.

Cheers,
David

On 1/20/07, M. Edward (Ed) Borasky removed_email_address@domain.invalid wrote:

Well … I don’t “get” Test::Unit. It just seems so complicated and
intricate. Rspec is a whole lot simpler to use, and it integrates some
good tools, like Rcov. I think it’s the perfect way to learn TDD/BDD.

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.

That is very interesting, I just recently did the same, set up a method
in
my testee

  def method

  end

and one more test passed I felt like a hero.
Now, maybe I should have felt like a Zero I think this question has a
lot to
do with abstraction
and I try very hard to abstract. It kind of forces your mind not to
think
about implementation
.
So that is the setup I am pretty sure, if it is always the right thing
to
do? Of course not!

It seems like a waste of time to do the

had to “create” the objects and methods and classes from the behavior.
Actually that is a really good point it is almost impossible to see a
stack
abstractly!
Stacks should be forbidden in tutorials anyway :slight_smile:

M. Edward (Ed) Borasky, FBG, AB, PTA, PGS, MS, MNLP, NST, ACMC§
http://borasky-research.blogspot.com/

If God had meant for carrots to be eaten cooked, He would have given
rabbits fire.

Cheers
Robert

On 1/19/07, nicknameoptional removed_email_address@domain.invalid wrote:

point I got was BDD try to break the 1-1 relation of class and test
class, which he said is useful if refactoring code. but writing rails
app, with convention over configuration ideology, I don’t really do
that much refactoring.

You may not now, but if you have to maintain your app over a long
period of time, with changing requirements, you will likely have to
some restructuring of some kind.

This is an interesting thing about Rails in general right now. It’s
still in its infancy and there aren’t too many companies besides 37
signals that have had to maintain Rails apps over several years. I
think as that happens that we’ll see more and more interest in
refactoring strategies and tools.

and if you look at the example,
@stack.should_be_empty” is mapped to stack.empty? method,
@stack.top.should_equal “one item” is stack.top == “one item”

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

It clarifies which comes first, the expected value or the actual value:

assert_equal(5, result) ???
assert_equal(result, 5) ???
result.should == 5

That’s pretty easy to get right.

On 1/19/07, nicknameoptional removed_email_address@domain.invalid wrote:

I just discovered rspec today, reading the example and tutorials,
besides the doc and coverage features, I can’t see how is it different
from unit test. For my rails app, existing testing tools in rails
already fills all my testing needs. So what does rspec do more than
existing testing tools? Thanks.

Disclaimer: I am the lead developer of rspec and freely admit whatever
bias that might bring.

RSpec is a tool which tries to make BDD easier. BDD is an approach to
development that tries to tackle some of the problems that development
teams (customers, developers and testers) run into doing TDD.

For me, BDD addressed some questions that I had at the time I first
heard about it, so I got involved. It has changed the way I approach
development regardless of platform or tools.

RSpec does not set out to do more from a testing perspective than
‘test/unit’ does. It just tries to help you see the whole process
through a slightly different lens.

If you’re not interested in seeing it through a different lens, there
may be no value in it for you. I can tell you that I’ve heard from
some skeptics who have really given it a shot that it does change the
way they approach testing.

Cheers,
David

On 1/20/07, M. Edward (Ed) Borasky removed_email_address@domain.invalid wrote:

intricate. Rspec is a whole lot simpler to use, and it integrates some
good tools, like Rcov. I think it’s the perfect way to learn TDD/BDD.

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.

This dates back to the beginnings of TDD. I just wrote about this in
another thread, but for completeness’ sake here: when you’re doing TDD
as prescribed, you run all of your unit tests very often. The fact
that they all pass gives you confidence to move quickly rather than
stop and wonder what you might be affecting that’s not immediately in
your view. If you make a change that introduces a problem and run the
tests right away, you discover the problem right away and don’t have
to start debugging the work you’ve done over the last
minutes/hours/days.

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 triviality of the fix is the beauty of the whole thing. Every
problem gets broken down into really tiny bite size problems. You
don’t have to hold up a delicate house of cards in your head that
falls down every time the phone rings.

Part of that may be the algorithm I’m implementing. It’s very well
defined already – not something I have to “figure out” given a set of
behaviors. But the same is true of a stack, which is the example in the
tutorial. Everybody knows what a stack is supposed to do, everybody
knows what the output from sorting an array of strings is supposed to
be, etc. I think a better example would be something where you didn’t
“instantly” know what the code should look like – a case where you
really had some behavior but no code when you started developent, and
had to “create” the objects and methods and classes from the behavior.

I agree. I’ll add a new tutorial to the rspec website sometime soon.

David

“nicknameoptional” removed_email_address@domain.invalid writes:

I just discovered rspec today, reading the example and tutorials,
besides the doc and coverage features, I can’t see how is it different
from unit test. For my rails app, existing testing tools in rails
already fills all my testing needs. So what does rspec do more than
existing testing tools? Thanks.

I don’t know about you, but since I use test/spec1 (my Test::Unit
based variant of RSpec), I enjoy writing tests and doing test-first a
lot more. I didn’t think it would make such a big difference, but it
really does.

(I hope to release test/spec 0.3 this week… speak up now if you wish
for anything.)

Christian N. wrote:

lot more. I didn’t think it would make such a big difference, but it
really does.

(I hope to release test/spec 0.3 this week… speak up now if you wish
for anything.)

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?

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

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

Hi Ed,

On 1/19/07, M. Edward (Ed) Borasky removed_email_address@domain.invalid wrote:

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.

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.

A few weeks ago I was doing BDD using RSpec and Francis H.'s MockFS
library (which mocks the file system). I needed to add a method to
MockFS to mock File#size. So I added a spec that called File#size,
and ran it. As expected, I got some error about File#size not found.
I looked through the MockFS code to see where this error came from,
and I saw that MockFS had an array of symbols which were the names of
the methods that it mocked. :size wasn’t in this array, which caused
the error. Looking at the MockFS code, I knew that I needed to do
two things: add :size to the array, and also implement the method that
mocked File#size. I remember being strongly tempted to do both these
changes before re-running the spec. But since I got the error because
:size wasn’t in the array, simply adding :size to the array was the
simplest thing that could possibly work. So I did that, and re-ran
the spec, knowing that I was going to get a NoMethodError. But
instead, ALL MY TESTS PASSED. I was quite surprised. Investigating
what had happened, I discovered that Francis implements the mock files
as StringIO objects, so StringIO#size got called, which returned the
size of the string/file, which was correct, so all the tests passed.
(Duck Typing in action).

If I hadn’t forced myself to try the simplest thing that could
possibly work, I would have had to implement (and debug) a File#size
mock method. This would have added unnecessary complexity to the
system. Worse, my experience is that once code gets implemented and
debugged, it rarely gets removed. So that code probably would have to
be maintained forever.

By forcing myself to always do the simplest thing that could possibly
work, I find that every day or two I come across a situation just like
this one, where a solution that I would have gladly bet serious money
that it was too simple to really work, actually does work. In
addition, every hour or two I find a solution that I thought might be
too simple to really work, that does work. Before I was doing BDD/TDD
I very rarely came up with simple solutions like this. The cumulative
effect is that my code is noticeably simpler and cleaner, and I find
this to be one of the major benefits I get from BDD/TDD.

Wayne


Wayne V.
No Bugs Software
Ruby, C# and Erlang Agile Contract Programming in Silicon Valley

Joel VanderWerf removed_email_address@domain.invalid 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.

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.