I don't get rspec

N

nicknameoptional

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
 
J

James Britt

nicknameoptional said:
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 Astels:

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



--
James Britt

"A language that doesn't affect the way you think about programming is
not worth knowing."
- A. Perlis
 
N

nicknameoptional

There is a good Google video about rspec and Behavior Driven

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

Sam Smoot

nicknameoptional said:
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.
 
L

Lionel Bouton

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

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

nicknameoptional

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

James Edward Gray II

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 Gray II
 
G

Gennady Bystritsky

------_=_NextPart_001_01C73C5A.E864A588
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

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:[email protected]]
Sent: Fri 1/19/2007 16:55
To: ruby-talk ML
Subject: Re: I don't get rspec
=20
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.




------_=_NextPart_001_01C73C5A.E864A588--
 
M

M. Edward (Ed) Borasky

nicknameoptional said:
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.
 
D

Devin Mullins

M. Edward (Ed) Borasky said:
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
 
P

Pat Maddox

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
 
D

David Chelimsky

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.

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
 
D

David Chelimsky

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
 
D

David Chelimsky

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.

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

David Chelimsky

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.

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
 
W

Wayne Vucenic

Hi Ed,

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 Hwang'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
 
J

Joel VanderWerf

Christian said:
nicknameoptional said:
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/spec[1] (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.

[1]: http://chneukirchen.org/blog/archiv...t-spec-0-2-a-bdd-interface-for-test-unit.html

(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?
 
G

Giles Bowkett

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. Like the only development involved was a bunch
of alias statements. But I was totally wrong. What you're really doing
is a more intuitive, smoother version of TDD which produces
documentation as its byproduct. TDD isn't really about testing -- it's
about design. BDD makes it easier to use TDD for what it's really for.
 
J

Jim Weirich

Giles said:
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!
 
D

David Chelimsky

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


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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,262
Messages
2,571,311
Members
47,986
Latest member
ColbyG935

Latest Threads

Top