Why detest rspec? (was: community poll about testing and spe

On 7/24/07, Nathaniel B. [email protected] wrote:

I may be biased, but I would really like and have been looking for an
alternative BDD choice besides RSpec.

What others are there? I have seen a couple by the likes of Ryan, even
Rick. Are any better? What about a conrast of testing libraries
highlighting the benefits and opinions of each?

I really want to get into testing beyond Test/Unit, but I detest the
RSpec library out of spite :slight_smile:

At the risk of shooting myself in the foot, Iā€™m really curious to know
why you detest RSpec.

I didnā€™t like it for a while because the syntax kept changing. This
made me rewrite the BDD section of my book twice (three times when I
rewrite to match 1.0).

But now that Iā€™ve been using the new syntax more, I like it. :stuck_out_tongue:

ā€“Jeremy

On 7/24/07, David C. [email protected] wrote:

I really want to get into testing beyond Test/Unit, but I detest the
RSpec library out of spite :slight_smile:

At the risk of shooting myself in the foot, Iā€™m really curious to know
why you detest RSpec.

ā€“
http://www.jeremymcanally.com/

My free Ruby e-book:
http://www.humblelittlerubybook.com/book/

My blogs:

http://www.rubyinpractice.com/

David C. wrote:

I may be biased, but I would really like and have been looking for an
alternative BDD choice besides RSpec.

What others are there? I have seen a couple by the likes of Ryan, even
Rick. Are any better? What about a conrast of testing libraries
highlighting the benefits and opinions of each?

I really want to get into testing beyond Test/Unit, but I detest the
RSpec library out of spite :slight_smile:

At the risk of shooting myself in the foot, Iā€™m really curious to know
why you detest RSpec.

Iā€™d like to chime in. I would not at all say that I detest RSpec in any
way, but I do find it to be rather besides the point. It just never
caught on to me, you know?

When I first looked at RSpec, I thought it was rather cryptic. This
boils down to a matter of taste, I know, but all those ā€œrecipesā€ (I
donā€™t know the term) really arenā€™t all that legible to me.
ā€œbowling.score.should == 0ā€? ā€œshouldā€ is equal to 0? Is it any more
expressive than ā€œassert 0, bowling.scoreā€? Again, itā€™s personal
preference, but this is one DSL that I donā€™t care for. So I dismissed it
in favor of the Test::Units I have come to cherish.

Then I attended a lecture by Aslak HellesƃĀøy. I mean, with so many people
around raving about RSpec, I must be missing the point right? But I was
let down: Alsak demonstrated it to be a wrapper DSL around Test::Unit
for ā€œpeople who find it hard to come to gripes with TDDā€. So itā€™s a sort
of workaround? I was disappointed by that statement of his.

He says Test::Unit is tightly coupled to the actual code and that thatā€™s
a bad thing. I say I like that coupling, because it keeps a sharp edge
on the test-before-you-write principle: if youā€™re mucking around code or
tests that worked before, youā€™ll find yourself pressed to advocate that
change and express it in an additional or revised test.

Moving from personal preference into the field of computer science,
there is no argument that I know of favoring either in code coverage or
testing metrics. (Indeed, ā€œcouplingā€ and ā€œcohesionā€ have so far only
referred to the functional components themselves, not their tests.) This
doesnā€™t prove either Alsak or me wrong or right, but does iterate that
itā€™s a matter of preference.

ā€œBut,ā€ some might say, ā€œweā€™re testing behavior here. Thatā€™s different.
We can clean up methods, throw code around, but as long as the behavior
remains the same, then thatā€™s OK.ā€ I see it as the same discussion about
white box testing and black box testing, but with a twist.

As a black box, the bowling example on the RSpec home page seems to work
fine. As a white box, itā€™s lacking in every respect because the
algorithm we assume to be present is, in fact, completely absent. I like
to test the algorithm, because if I donā€™t prove the behavior of the
algorithm to be correct then I will need to verify every possible
outcome instead. That kind of verification isnā€™t very efficient.

So the twist is this: this time around, weā€™re mixing up black box
testing by dubbing it ā€œbehaviorā€ and white box testing by performing
actual method calls. Iā€™ve been searching for a rationale, but could only
find the one by Alsak that I was disappointed by before.

The way I see it, RSpec is just a matter of preference, and a bit of a
hype at that. Perhaps Iā€™m misunderstanding, and if so, Iā€™d love to see
the entire mantra clarified. But until then, Iā€™m preferring Test::Unit
for its readability and code coupling, and saying nay to all those who
preach that RSpec is a level beyond Test::Unit.

Looking forward to your responses.

ā€“
Roderick van Domburg

Perhaps Iā€™m misunderstanding, and if so Iā€™d certainly appreciate it if

@Roderick:
Wow. That mirrors my thoughts exactly. Iā€™d love for someone to chime in
and
counter this. Thanks for putting it so well.

Roderick: David C. might be a little miffed with your selective
quoting which makes it appear as if he doesnā€™t like RSpecā€¦

David C. wrote:

I may be biased, but I would really like and have been looking for an
alternative BDD choice besides RSpec.

This was not written by David, but was written in response to an email
from
him. The only clue to this is the level of indentation of the quoting.

James.

Alsak demonstrated it to be a wrapper DSL around Test::Unit
for ā€œpeople who find it hard to come to gripes with TDDā€. So itā€™s a sort
of workaround? I was disappointed by that statement of his.

I donā€™t get it. What can you write in RSpec that you canā€™t write,
nearly the same way, in Test::Unit?

He says Test::Unit is tightly coupled to the actual code and that thatā€™s
a bad thing.

Done right, either one tightly coheres to the actual code.

(Define ā€œcoupleā€ as ā€œA must change only because B changedā€, and define
ā€œcohereā€ as ā€œA and B share legitimate reasons to change togetherā€.)

ā€“
Phlip
http://www.oreilly.com/catalog/9780596510657/
ā€œTest Driven Ajax (on Rails)ā€
assert_xpath, assert_javascript, & assert_ajax

On 7/25/07, Roderick van Domburg [email protected]
wrote:

RSpec library out of spite :slight_smile:
donā€™t know the term) really arenā€™t all that legible to me.

doesnā€™t prove either Alsak or me wrong or right, but does iterate that
to test the algorithm, because if I donā€™t prove the behavior of the
the entire mantra clarified. But until then, Iā€™m preferring Test::Unit
for its readability and code coupling, and saying nay to all those who
preach that RSpec is a level beyond Test::Unit.

Iā€™m sorry that you see this as preaching and mantras. I have no
intention of converting you. I like RSpec because it expresses the
things I want in a BDD framework. You donā€™t have to like it.

BDD comes from TDD, which comes from XP, which includes Refactoring as
an integral part of the process. Refactoring is more expensive as your
tests are more tightly coupled to the code, so one goal of TDD is to
decouple the tests from the detail of the code (which is what changes
most often). One thing that aids in this decoupling is focusing on
behaviour instead of internal implementation. BDD champions this goal
by putting it front and center. RSpec supports this by trying to use
words like ā€œdescribeā€ instead of ā€œTestCaseā€ and ā€œshouldā€ instead of
ā€œassert.ā€

It is clear from your arguments that a) your testing goals do not
align with those of RSpec and b) youā€™ve only read the cover (your
argument about the example on the Home Page). If youā€™re seriously
interested in learning about RSpec and BDD, then you should try to
actually use it on a small project and see how it feels. If not, then
so be it. I still get to use it, so I am happy.

Cheers,
David

On 7/25/07, Roderick van Domburg [email protected]
wrote:

in favor of the Test::Units I have come to cherish.
Cryptic? Seriously?
ā€œbowling score should equal 0ā€
vs
ā€œassert 0 bowling scoreā€

The first statement is parseable by a second grader. The second
statement only makes sense if you are very familiar with test::unit.

I think the problem is that youā€™re looking at the code and ignoring
the meaning. You ask ā€œā€˜shouldā€™ is equal to 0?ā€ It seems that youā€™re
examining the code the way the interpretter would, and thinking, ā€œthe
object returned by the method should is equal to 0.ā€ Thatā€™s
completely the wrong mindset.

I would say that TDD is a tool to help you solve the problem of
designing and implementing behavior. Test::Unit works fine in that
regard, but RSpec reduces the semantic distance between the developer
and the problem domain.

Consider a task list you write for yourself. Again youā€™ll have
statements that look like ā€œbowling score should equal 0ā€ rather than
ā€œassert 0 bowling score.ā€ Throw in a couple dots and youā€™re good to
go :slight_smile: RSpec lets you express behavior in code almost as neatly as you
do in your head. Thatā€™s very, very powerful. Iā€™ve yet to come across
a tool that brings you that close.

Then I attended a lecture by Aslak HellesĆøy. I mean, with so many people
around raving about RSpec, I must be missing the point right? But I was
let down: Alsak demonstrated it to be a wrapper DSL around Test::Unit
for ā€œpeople who find it hard to come to gripes with TDDā€. So itā€™s a sort
of workaround? I was disappointed by that statement of his.

Iā€™m not sure how long ago that lecture was, but to the best of my
knowledge RSpec is no longer just a wrapper around Test::Unit. On the
other hand, Iā€™m not sure why it matters how itā€™s implemented under the
hood. We are concerned with behavior here, after all :wink:

Anyway, the big BDD guys all basically say that thereā€™s nothing
different if youā€™re doing TDD right. BDD/RSpec isnā€™t a workaround to
TDD, but rather a fast track to the good things about TDD. Again you
have the benefit of a shorter semantic distance. By using RSpec you
start off focusing on design and behavior, which is the ultimate goal
of TDD.

He says Test::Unit is tightly coupled to the actual code and that thatā€™s
a bad thing. I say I like that coupling, because it keeps a sharp edge
on the test-before-you-write principle: if youā€™re mucking around code or
tests that worked before, youā€™ll find yourself pressed to advocate that
change and express it in an additional or revised test.

The concern is that Test::Unit encourages an artificial coupling of
one test class to one production class. Thatā€™s a completely different
thing from tests being coupled to the code, which as you pointed out
will/should be the case. The problem is that a new test class can
feel heavy weight (especially if youā€™ve been using JUnit for several
years, you almost certainly have that stigma). People think, ā€œwow why
should I create a whole new class when itā€™s just a little bit of
behavior?ā€ Most people know that itā€™s not a good idea to have a class
with just one or two methods, but testing has different rules and the
fact is that a test class with just a few methods is often precisely
what you need.

RSpec helps you avoid this problem by encouraging you to write several
small, focused examples. Once again itā€™s not something that you
couldnā€™t do with Test::Unit, but the RSpec way is just a lot closer to
the Right Way.

white box testing and black box testing, but with a twist.

As a black box, the bowling example on the RSpec home page seems to work
fine. As a white box, itā€™s lacking in every respect because the
algorithm we assume to be present is, in fact, completely absent. I like
to test the algorithm, because if I donā€™t prove the behavior of the
algorithm to be correct then I will need to verify every possible
outcome instead. That kind of verification isnā€™t very efficient.

I donā€™t think RSpec is meant to be a white-box testing tool. Again,
itā€™s all about design and behavior. Despite that, you should still be
able to achieve a sufficient level of white-box testing using mocks.

In fact, sometimes Iā€™ll write two sets of specs for the same example.
One will use concrete implementations, allowing me to verify that I
get the desired side-effects (records created, etc). Another one will
use mocks, allowing me to verify that the proper interactions are
being made. Iā€™ve got a good example, but I donā€™t want to add 65 lines
of code to this already lengthy messageā€¦but if thereā€™s any interest
Iā€™ll be happy to post it in a followup message.

So the twist is this: this time around, weā€™re mixing up black box
testing by dubbing it ā€œbehaviorā€ and white box testing by performing
actual method calls. Iā€™ve been searching for a rationale, but could only
find the one by Alsak that I was disappointed by before.

The way I see it, RSpec is just a matter of preference, and a bit of a
hype at that. Perhaps Iā€™m misunderstanding, and if so, Iā€™d love to see
the entire mantra clarified. But until then, Iā€™m preferring Test::Unit
for its readability and code coupling, and saying nay to all those who
preach that RSpec is a level beyond Test::Unit.

Sure, just as some people prefer C. Itā€™s certainly more readable -
you have semicolons that tell you where a statement ends!

Pat

Thanks for your replies everyone ā€“ it sure has been improving my
understanding, plus I love the debate. :slight_smile:

Allow me to respond chronologically.

Phlip wrote:

Alsak demonstrated it to be a wrapper DSL around Test::Unit
for ā€œpeople who find it hard to come to gripes with TDDā€. So itā€™s a sort
of workaround? I was disappointed by that statement of his.

I donā€™t get it. What can you write in RSpec that you canā€™t write,
nearly the same way, in Test::Unit?

That was exactly my point.

Phlip wrote:

He says Test::Unit is tightly coupled to the actual code and that thatā€™s
a bad thing.

Done right, either one tightly coheres to the actual code.

(Define ā€œcoupleā€ as ā€œA must change only because B changedā€, and define
ā€œcohereā€ as ā€œA and B share legitimate reasons to change togetherā€.)

That was me quoting him. Both Alsak and you are right. :slight_smile:

Alsak is right in the sense that tight coupling indeed does not improve
testability or robustness because a network of modules that are
interrelated are more difficult to test than modules in isolation.

I totally agree with you on the cohesion tab. Cohesion (singleness of
purposeness of a module) is generally regarded as a good thing to have
in computer science and is indicative of a well-designed software
architecture that is reusable and understandable.

In fact, it is often said that a high cohesion correlates with high test
coverage, because a single test will touch on multiple facets of the
module, and hence multiple tests will cover the facets multiple times.

But hereā€™s the thing: these quality measures are about intra- or
inter-relationships between functional modules ā€“ not between a
functional module and its unit tests. When we speak in this context of
modules and their unit tests, I have yet to find any evidence that
either refer cohesion or coupling is either desirable or undesirable.

The point Iā€™m trying to make here is this: with ā€œtight couplingā€ [sic.]
being listed as one of the reasons to move away from Test::Unit, that
really just is preference over fact.

James M. wrote:

Roderick: David C. might be a little miffed with your selective
quoting which makes it appear as if he doesnā€™t like RSpecā€¦

David C. wrote:

I may be biased, but I would really like and have been looking for an
alternative BDD choice besides RSpec.

This was not written by David, but was written in response to an email
from him. The only clue to this is the level of indentation of the quoting.

I apologize for my misquoting. It is not my intention to bring either
discredit or misuse their words.

David C. wrote:

Iā€™m sorry that you see this as preaching and mantras. I have no
intention of converting you. I like RSpec because it expresses the
things I want in a BDD framework. You donā€™t have to like it.

But maybe I donā€™t know what Iā€™m missing, in which case I want to like
it! :slight_smile:

David C. wrote:

BDD comes from TDD, which comes from XP, which includes Refactoring as
an integral part of the process. Refactoring is more expensive as your
tests are more tightly coupled to the code, so one goal of TDD is to
decouple the tests from the detail of the code (which is what changes
most often). One thing that aids in this decoupling is focusing on
behaviour instead of internal implementation. BDD champions this goal
by putting it front and center. RSpec supports this by trying to use
words like ā€œdescribeā€ instead of ā€œTestCaseā€ and ā€œshouldā€ instead of
ā€œassert.ā€

I do acknowledge the design goals, but keep wondering: how can only
words make the difference between BDD and TDD? I fail to see how
replacing words and reshuffling parameters (i.e. assert 0, bowling.score
ā†’ bowling.score.should == 0) can facilitate the decoupling / decrease
in cohesion.

David C. wrote:

It is clear from your arguments that a) your testing goals do not
align with those of RSpec and b) youā€™ve only read the cover (your
argument about the example on the Home Page). If youā€™re seriously
interested in learning about RSpec and BDD, then you should try to
actually use it on a small project and see how it feels. If not, then
so be it. I still get to use it, so I am happy.

You are absolutely right in this. I should truly give it a whirl and
havenā€™t yet. I only checked out the examples and attended Alsakā€™s 2007
lecture. Not trying sure is bad developer practice :slight_smile: Thanks for point
that out to me, itā€™s a good reality check.

Could you tell me though, what is the gap that you perceive between my
testing goals and those of RSpec? That knowledge would be really helpful
in completing my mental picture about RSpec.

Pat M. wrote:

On 7/25/07, Roderick van Domburg [email protected]
wrote:

in favor of the Test::Units I have come to cherish.
Cryptic? Seriously?
ā€œbowling score should equal 0ā€
vs
ā€œassert 0 bowling scoreā€

Again, thanks! I was reading aloud: ā€œbowling score should is equal to
0ā€. Never thought of keeping it simpler than that.

Pat M. wrote:

Then I attended a lecture by Aslak HellesĆÆĀæĀ½y. I mean, with so many people
around raving about RSpec, I must be missing the point right? But I was
let down: Alsak demonstrated it to be a wrapper DSL around Test::Unit
for ā€œpeople who find it hard to come to gripes with TDDā€. So itā€™s a sort
of workaround? I was disappointed by that statement of his.

Iā€™m not sure how long ago that lecture was, but to the best of my
knowledge RSpec is no longer just a wrapper around Test::Unit. On the
other hand, Iā€™m not sure why it matters how itā€™s implemented under the
hood. We are concerned with behavior here, after all :wink:

Indeed that was my perception of things, not something he said.

Earlier Philip asked ā€œI donā€™t get it. What can you write in RSpec that
you canā€™t write, nearly the same way, in Test::Unit?ā€. Thatā€™s the same
flow of mind that got me to arrive to this perception.

Pat M. wrote:

He says Test::Unit is tightly coupled to the actual code and that thatā€™s
a bad thing. I say I like that coupling, because it keeps a sharp edge
on the test-before-you-write principle: if youā€™re mucking around code or
tests that worked before, youā€™ll find yourself pressed to advocate that
change and express it in an additional or revised test.

The concern is that Test::Unit encourages an artificial coupling of
one test class to one production class. Thatā€™s a completely different
thing from tests being coupled to the code, which as you pointed out
will/should be the case. The problem is that a new test class can
feel heavy weight (especially if youā€™ve been using JUnit for several
years, you almost certainly have that stigma). People think, ā€œwow why
should I create a whole new class when itā€™s just a little bit of
behavior?ā€ Most people know that itā€™s not a good idea to have a class
with just one or two methods, but testing has different rules and the
fact is that a test class with just a few methods is often precisely
what you need.

RSpec helps you avoid this problem by encouraging you to write several
small, focused examples. Once again itā€™s not something that you
couldnā€™t do with Test::Unit, but the RSpec way is just a lot closer to
the Right Way.

That did put things into perspective for me. Thanks!

Pat M. wrote:

As a black box, the bowling example on the RSpec home page seems to work
fine. As a white box, itā€™s lacking in every respect because the
algorithm we assume to be present is, in fact, completely absent. I like
to test the algorithm, because if I donā€™t prove the behavior of the
algorithm to be correct then I will need to verify every possible
outcome instead. That kind of verification isnā€™t very efficient.

I donā€™t think RSpec is meant to be a white-box testing tool. Again,
itā€™s all about design and behavior. Despite that, you should still be
able to achieve a sufficient level of white-box testing using mocks.

In fact, sometimes Iā€™ll write two sets of specs for the same example.
One will use concrete implementations, allowing me to verify that I
get the desired side-effects (records created, etc). Another one will
use mocks, allowing me to verify that the proper interactions are
being made. Iā€™ve got a good example, but I donā€™t want to add 65 lines
of code to this already lengthy messageā€¦but if thereā€™s any interest
Iā€™ll be happy to post it in a followup message.

I am interested! I enjoy the discussion and think itā€™ll be 65 lines well
spent. :slight_smile:

Cheers,

Roderick

On 7/26/07, Jacob A. [email protected] wrote:

This sounds very interesting. I would love to see a concrete example
detailing your approach.

Okay, here we go :slight_smile:

describe VideoService, " when creating a video" do
fixtures :companies, :sites, :video_formats, :publish_settings

before(:each) do
@video = Video.new
@video.company = companies(:test)
@video.site = sites(:test)
sites(:test).stub!(:formats).and_return [ video_formats(:flash) ]

@origin = mock_model(Origin, :process_source => true,

:transcode_asset => true, :storage => ā€œfileā€)
Origin.stub!(:find_transcoder).and_return @origin

@service = VideoService.new

end

def create_video
@service.create_video :video => @video, :signature => ā€œabc123ā€,
:frame => 1, :storage => ā€œfileā€
end

it ā€œshould add a new video recordā€ do
lambda { create_video }.should change(Video, :count).by(1)
end

it ā€œshould create two assets - one source and one transcodedā€ do
lambda { create_video }.should change(Asset, :count).by(2)
@video.source_asset.should be_source
@video.should have(2).assets
end

it ā€œshould create the main asset with the appropriate video formatā€ do
create_video
@video.assets.find_by_video_format_id(video_formats(:flash).id).should_not
be_blank
end
end

describe VideoService, " when creating a video" do
fixtures :companies, :sites, :video_formats

before(:each) do
@video = mock_model(Video, :save => true, :company_id =>
companies(:test).id, :site => sites(:test), :hook => nil)
sites(:test).stub!(:formats).and_return [ video_formats(:flash) ]

@source_asset = mock_model(Asset, :video_id= => @video.id, :save => 

true)
@transcode_asset = mock_model(Asset, :video_id= => @video.id, :save
=> true)
Asset.stub!(:new).and_return @source_asset, @transcode_asset
@video.stub!(:source_asset).and_return @source_asset

@source_origin = mock_model(Origin, :process_source => true,

:transcode_asset => true, :storage => ā€œfileā€)
@transcode_origin = mock_model(Origin, :transcode_asset => true,
:storage => ā€œfileā€)
Origin.stub!(:find_transcoder).and_return @source_origin,
@transcode_origin

@service = VideoService.new

end

def create_video
@service.create_video :video => @video, :signature => ā€œabc123ā€,
:frame => 1, :storage => ā€œfileā€
end

it ā€œshould find a transcoderā€ do
Origin.should_receive(:find_transcoder).with(companies(:test).id,
false, ā€œfileā€).and_return @source_origin
create_video
end

it ā€œshould process the source assetā€ do
@source_origin.should_receive(:process_source).with(ā€œabc123ā€,
@source_asset, 1, ā€œhttp://test.host:80/ā€)
create_video
end

it ā€œshould find an origin for the transcode formatā€ do
Origin.should_receive(:find_transcoder).with(companies(:test).id,
false, nil).and_return @transcode_origin
create_video
end

it ā€œshould transcode the new assetā€ do
@transcode_origin.should_receive(:transcode_asset).with(ā€œabc123ā€,
@transcode_asset, ā€œhttp://test.host:80/ā€,
ā€œhttp://test.host:80/video_formats/#{video_formats(:flash).id}.xmlā€)
create_video
end
end

I created the VideoService to wrap the creation of a video in our
system. At that stage in the code, there were a couple main parts -
creating a new video record, creating a couple asset records, and
notifying our transcode machines about the new assets.

The first example specifies the db behavior I want. That was my
black-box test (you might say itā€™s grey-box because Iā€™m stubbing some
stuff out, but that wasnā€™t part of the original spec. Itā€™s just there
so the spec can run - Origin makes a network call and itā€™s easier to
stub the whole thing out).

The second example is the white-box test, which verifies that the
internals work. Certain origins should be found, they need to receive
certain calls with a particular video, etc.

Now Iā€™m not sure if people will like those specs :slight_smile: but hopefully it
gives you an idea of how you can approach specifications from both
angles.

Pat

On 7/26/07, Roderick van Domburg [email protected]
wrote:

Could you tell me though, what is the gap that you perceive between my
testing goals and those of RSpec? That knowledge would be really helpful
in completing my mental picture about RSpec.

My perception is based on your statement that you find the tight
coupling between tests and the subject code to be a good thing, and
that you like the fact that making changes to code forces you to make
changes to your tests.

Compare this to TDDā€™s goal of supporting inexpensive refactoring
through very loose coupling between tests and code.

I also sensed that you donā€™t find value in focusing the discussion on
behaviour:

=============================================
ā€œBut,ā€ some might say, ā€œweā€™re testing behavior here.ā€

To me, putting the focus on behaviour encourages a subtle, yet
powerful change in how you perceive these things we call
tests/specs/examples, etc. Obviously, RSpec is interested in helping
you to think of tests as executable examples of expected behaviour as
opposed to, well, tests.

This help?

David C. wrote:

To me, putting the focus on behaviour encourages a subtle, yet
powerful change in how you perceive these things we call
tests/specs/examples, etc. Obviously, RSpec is interested in helping
you to think of tests as executable examples of expected behaviour as
opposed to, well, tests.

This help?

Yes, that is a metaphor that sticks.

All that rests now is how ā€œrenamingā€ assert(x, y) to Object#should truly
facilitates that idea. Yes there are other niceties and syntactic sugar,
but isnā€™t providing a humanized DSL really the gist of it all?

In the end, youā€™ll still be comparing method results and variable
assignments.

ā€“
Roderick van Domburg

Pat M. wrote:

In fact, sometimes Iā€™ll write two sets of specs for the same example.
One will use concrete implementations, allowing me to verify that I
get the desired side-effects (records created, etc). Another one will
use mocks, allowing me to verify that the proper interactions are
being made. Iā€™ve got a good example, but I donā€™t want to add 65 lines
of code to this already lengthy messageā€¦but if thereā€™s any interest
Iā€™ll be happy to post it in a followup message.

This sounds very interesting. I would love to see a concrete example
detailing your approach.

ā€“
Cheers,

  • Jacob A.

Roderick van Domburg wrote:

All that rests now is how ā€œrenamingā€ assert(x, y) to Object#should truly
facilitates that idea. Yes there are other niceties and syntactic sugar,
but isnā€™t providing a humanized DSL really the gist of it all?

In the end, youā€™ll still be comparing method results and variable
assignments.

Yes, in the endā€¦ you see a result like this. But, Iā€™d like to back
this up to before you write your code.

Letā€™s start with a high-level business rule for an application. We might
have a discussion with our client and determine the following.

A user should not be allowed to create a new account when providing an
existing email address.

This is something that weā€™d have our clients agree upon before we ever
touched any code. When it comes time to implement this behavior into the
application, we can translate this into RSpec very easily.

describe User, ā€œnew accountā€ do

it ā€œshould not be allowed to create a new account when providing an
existing email address.ā€

end

When we run our specs, this will show up as unimplemented. I often add
several of these once a client has signed off on some specifications,
and it results in a TODO-list for me. At this point, I can begin turning
these into full specs.

In a nuthsell, itā€™s not just a DSL for Rubyā€¦ itā€™s provides a framework
for discussing requirements with our clients and Interaction Design
team. Itā€™s clear English and leaves little room for ambiguity, which I
believe is a good thing! :slight_smile:

If you enjoy translating high-level requirements into Test::Unitā€¦ and
donā€™t mind the underscore/camelcase madenessā€¦ well, good luck with
that. I switched to Ruby/Rails because of how expressive and
English-like it was and think that itā€™s very fitting that RSpec would
evolve out of this community.

Cheers,
Robby

ā€“
Robby R.
http://www.robbyonrails.com/

Hi ā€“

On Thu, 26 Jul 2007, Robby R. wrote:

When we run our specs, this will show up as unimplemented. I often add
donā€™t mind the underscore/camelcase madenessā€¦ well, good luck with
that. I switched to Ruby/Rails because of how expressive and
English-like it was and think that itā€™s very fitting that RSpec would
evolve out of this community.

OKā€¦ but, lest we forget, Nathanielā€™s work on test/unit ā€“ past,
present, and future (I hope) ā€“ has played an incalculable role in
shaping the Ruby programming culture. Luckily, itā€™s not a zero-sum
game; people can delve into RSpec without having to jettison or scoff
at test/unit. Itā€™s possible for two highly-accomplished test
frameworks to evolve out of the same community :slight_smile:

(Iā€™m not trying to get you to like test/unit; Iā€™m just putting in a
word for not having it have to be a winner-take-all kind of
relationship, and also eager to keep the significance of test/unit to
Ruby culture on the radar. I know Iā€™m showing my age ā€“ in this case,
almost seven :slight_smile:

David

ā€“

On 7/27/07, [email protected] [email protected] wrote:

for discussing requirements with our clients and Interaction Design
present, and future (I hope) ā€“ has played an incalculable role in
shaping the Ruby programming culture. Luckily, itā€™s not a zero-sum
game; people can delve into RSpec without having to jettison or scoff
at test/unit. Itā€™s possible for two highly-accomplished test
frameworks to evolve out of the same community :slight_smile:

More than two. Donā€™t forget watir. And all of the mocking frameworks.
Thereā€™s a lot of good stuff here.

(Iā€™m not trying to get you to like test/unit; Iā€™m just putting in a
word for not having it have to be a winner-take-all kind of
relationship, and also eager to keep the significance of test/unit to
Ruby culture on the radar.

A very important point. And now that Ryan has taken over maintenance
of test/unit, I expect to see some great new ideas appearing there as
well.

The thing about RSpec is that it is intended to be a BDD framework,
not a testing framework. It aims to support a behaviour-focused
process in which you, in very granular steps, describe a bit of
behaviour and then implement it.

But BDD is not the end of the testing story on any project. At least I
donā€™t think it should be. Some might even say itā€™s not part of the
testing story at all :slight_smile:

A perfect example is Matrix Testing, introduced by ZenTest. In
fairness, I havenā€™t done this yet, but I can imagine a process that
goes like this:

  1. Develop a component using TDD (and RSpec) to encourage simple
    design and usable APIs.
  2. Write a matrix test (using ZenTest with test/unit) to ensure that
    youā€™ve covered all of the permutations you anticipate.
  3. If the matrix test exposes any holes, go back and use RSpec to
    drive the process of plugging them.

I can hear some saying ā€œbut thatā€™s doing the same work twice. Why not
just a Matrix Test to begin with and call it a day?ā€

Because these two tools/approaches solve different problems. RSpec/BDD
is good at expressing behaviour and encouraging simple, flexible
designs. MatrixTesting is good at expressing multiple permutations in
a clean and simple way. Used together, I believe that youā€™d end up
with a simpler design with better test coverage than you would with
either tool alone.

In XP we do Customer Tests and Developer Tests, though these have a
lot of different names. They are, in the end, exercising the same
code. But they express very different things. And what my experience
tells me is that itā€™s the combination of layers of testing that proves
most effective. So for me, this notion of combining a BDD framework
(for DESIGN) with a testing framework (for TESTING) makes perfect
sense.

I know Iā€™m showing my age ā€“ in this case,
almost seven :slight_smile:

Happy Birthday (6 year olds only say ā€œalmost 7ā€ when itā€™s just a few
days away).

Cheers,
David

Many thanks for taking the time to write down your thoughts, everyone.
Itā€™s been very helpful to me to put RSpec in perspective. Iā€™ll take it
for a whirl like David suggested, and will revisit this topic if RSpec
manages to win me over. :slight_smile:

ā€“
Roderick van Domburg

This argument is the same one you could use to say ā€œwhat can you
write in Ruby that you canā€™t write, nearly the same way, in Cā€? Heck,
they are both TC general purpose computer programming languages.
Ahhhh, but the ā€œfeelā€ is different. Thatā€™s what I find sets RSpec
apart, and if it doesnā€™t click for you it might not work for you.

On 7/26/07, Roderick van Domburg [email protected]
wrote:

All that rests now is how ā€œrenamingā€ assert(x, y) to Object#should truly
facilitates that idea.

I think this is one of several aspects of RSpec that help promote this
idea. I do thing that saying ā€œshouldā€ instead of ā€œassertā€ changes the
feel from tests to examples of behaviour. But itā€™s not limited to
that.

The structure/organization using describe/it instead of
TestCase/test_method and, especially, using strings to express the
intent rather than method names both go a long way to support this
shift in focus. The reporting you get helps as well.

David

On Jul 25, 2007, at 11:50 AM, David C. wrote:

RSpec supports this by trying to use words like ā€œdescribeā€ instead
of ā€œTestCaseā€ and ā€œshouldā€ instead of ā€œassert.ā€

As an aside, RSpecā€™s use of ā€œshouldā€ may be confusing to anyone
coming from the networking world:

http://www.faqs.org/rfcs/rfc2119.html

-faisal