Forum: RSpec newbie cucumber tutorial

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
20ee0d23c969c7740d3c936a4675bb23?d=identicon&s=25 Sarah Allen (ultrasaurus)
on 2008-12-22 10:01
I got started with cucumber and it sure is fun.  I've written up my
initial experience in tutorial format here for any newbies who want to
follow in my tracks:
http://www.ultrasaurus.com/code/2008/12/rails-2-day-3.html

If anyone has any corrections, let me know.  I was wondering whether
when writing a real application, do you usually write your whole spec
with lots of scenarios at once and then get them the execute one at a
time? or do you write and code one scenario at a time?

Thanks,
Sarah

p.s. what is the relationship between cucumber and RSpec?
Cdf378de2284d8acf137122e541caa28?d=identicon&s=25 Matt Wynne (mattwynne)
on 2008-12-22 10:49
(Received via mailing list)
Great stuff.

One thing I'd point out is the missing (and extremely important) step
3.5 in Rick Denatale's TDD steps: *Refactor to remove duplication*.

Not that there's any refactoring necessary in your example, but it's
always worth reminding people they should check for it.

On 22 Dec 2008, at 09:01, Sarah Allen wrote:

> I got started with cucumber and it sure is fun.  I've written up my
> initial experience in tutorial format here for any newbies who want to
> follow in my tracks:
> http://www.ultrasaurus.com/code/2008/12/rails-2-day-3.html
>
> If anyone has any corrections, let me know.  I was wondering whether
> when writing a real application, do you usually write your whole spec
> with lots of scenarios at once and then get them the execute one at a
> time? or do you write and code one scenario at a time?

Mostly I pick off a simple scenario, write it into Cucumber, then dive
into the code to make it work. Then when I'm back on the surface with
the scenario passing, I think about the next simplest scenario, write
that up into a feature, and I'm off again.

Sometimes I keep a list (you can use # to comment lines in
the .feature file) of scenarios I'm going to write up later, so I have
a kind of 'todo list' but I don't usually flesh them out into
executable scenarios with steps until I'm ready to work on them.

> p.s. what is the relationship between cucumber and RSpec?

Short version: RSpec is for unit testing, Cucumber is for acceptance
testing.


Matt Wynne
http://blog.mattwynne.net
http://www.songkick.com
0be0e4aa42aacd9a8a95c792de273ca7?d=identicon&s=25 Aslak Hellesøy (aslakhellesoy)
on 2008-12-22 12:15
(Received via mailing list)
On Mon, Dec 22, 2008 at 10:01 AM, Sarah Allen <lists@ruby-forum.com>
wrote:

> I got started with cucumber and it sure is fun.  I've written up my
> initial experience in tutorial format here for any newbies who want to
> follow in my tracks:
> http://www.ultrasaurus.com/code/2008/12/rails-2-day-3.html
>
> If anyone has any corrections, let me know.  I was wondering whether
> when writing a real application, do you usually write your whole spec
> with lots of scenarios at once and then get them the execute one at a
> time? or do you write and code one scenario at a time?
>

Hi Sarah,

Thanks for the great writeup. It is simple to follow and explains what's
going on really well. I have a few comments:

* I released 0.1.13 yesterday. In the Rails installation wiki page I
recommend using my webrat gem. It lets you use response.should
have_selector(...) (You're not using it in your tutorial, but just in
case...)
* "Write a Spec" should be "Write a feature" (specs is confusing here
because that is what people use RSpec for. describe and it style). There
are
some other refs to "spec" which should be "feature".
* Use bang! methods when creating records. Otherwise a failure to create
will silently pass without you knowing. Example:

task = Task.new(:description => desc) # Lose the semicolon
task.save!

Or simpler:
Task.create!(:description => desc)

Cheers,
Aslak
20ee0d23c969c7740d3c936a4675bb23?d=identicon&s=25 Sarah Allen (ultrasaurus)
on 2008-12-22 17:59
Aslak Hellesøy wrote:
> * I released 0.1.13 yesterday. In the Rails installation wiki page I
> recommend using my webrat gem. It lets you use response.should
> have_selector(...) (You're not using it in your tutorial, but just in
> case...)

Luckily I started with cucumber on Sunday just after your release, so
I'm using that version.  What does have_selector do?  (Is there an API
reference somewhere that I missed?)

> * "Write a Spec" should be "Write a feature" (specs is confusing here
> because that is what people use RSpec for. describe and it style). There
> are
> some other refs to "spec" which should be "feature".

I changed it to "describe a feature," since to me "write a feature"
means writing the code.  When I started using cucumber, I thought it was
part of RSpec.  The cucumber .feature files still feel like a spec to me
and since I've never used RSpec, I don't really appreciate the
distinction.

> * Use bang! methods when creating records. Otherwise a failure to create
> will silently pass without you knowing. Example:
>
> task = Task.new(:description => desc) # Lose the semicolon
> task.save!
>
> Or simpler:
> Task.create!(:description => desc)

Thanks for the tip.  As you can see from my series of blog posts, I'm
new to Ruby and Rails.  I thought that ending a method with ! was a
naming convention.  Reading the humble ruby book it says "Another
convention to follow is that if the method modifies its receiver in
place (i.e. the method modifies the object that called it), then it
should end in an exclamation point" and the Rails doc show examples of
create without !
http://api.rubyonrails.org/classes/ActiveRecord/Ba... but if
I make the change you suggest the test passes.  I've updated the
tutorial and my code, but I'm confused.

Fun stuff. Thanks for making this!

Sarah
0be0e4aa42aacd9a8a95c792de273ca7?d=identicon&s=25 Aslak Hellesøy (aslakhellesoy)
on 2008-12-22 18:25
(Received via mailing list)
On Mon, Dec 22, 2008 at 5:59 PM, Sarah Allen <lists@ruby-forum.com>
wrote:

> Aslak Hellesøy wrote:
> > * I released 0.1.13 yesterday. In the Rails installation wiki page I
> > recommend using my webrat gem. It lets you use response.should
> > have_selector(...) (You're not using it in your tutorial, but just in
> > case...)
>
> Luckily I started with cucumber on Sunday just after your release, so
> I'm using that version.  What does have_selector do?  (Is there an API
> reference somewhere that I missed?)
>

That's part of the WebRat API:
http://gitrdoc.com/brynary/webrat/tree/master/


>
> > * "Write a Spec" should be "Write a feature" (specs is confusing here
> > because that is what people use RSpec for. describe and it style). There
> > are
> > some other refs to "spec" which should be "feature".
>
> I changed it to "describe a feature," since to me "write a feature"
> means writing the code.


"Cucumber Feature Description" is probably a better term.


> When I started using cucumber, I thought it was
> part of RSpec.


It's not part of RSpec, but grew out of it.


> The cucumber .feature files still feel like a spec to me
> and since I've never used RSpec, I don't really appreciate the
> distinction.
>

They are two different projects. RSpec is for lower levels (objects). A
"test" in RSpec is called a spec. A "test" in Cucumber is called a
Feature.


> Thanks for the tip.  As you can see from my series of blog posts, I'm
> new to Ruby and Rails.  I thought that ending a method with ! was a
> naming convention.  Reading the humble ruby book it says "Another
> convention to follow is that if the method modifies its receiver in
> place (i.e. the method modifies the object that called it), then it
> should end in an exclamation point" and the Rails doc show examples of
> create without !
> http://api.rubyonrails.org/classes/ActiveRecord/Ba... but if
> I make the change you suggest the test passes.  I've updated the
> tutorial and my code, but I'm confused.
>

The #create! method is documented here:
http://api.rubyonrails.org/classes/ActiveRecord/Va...

Essentially, #create will never raise an error no matter what you pass
it,
and you actually want exceptions for bad input in your tests (step
definitions).
Therefore - use #create! (or #save!). In your app, use the non-bang
methods.

Cheers,
Aslak
20ee0d23c969c7740d3c936a4675bb23?d=identicon&s=25 Sarah Allen (ultrasaurus)
on 2008-12-22 20:09
I realize this is off-topic for the RSpec forum and cucumber tutorial,
but I'm hoping you'll enlighten me on this point which is, I guess, more
of a Ruby language question...

Aslak Hellesøy wrote:
>> As you can see from my series of blog posts, I'm
>> new to Ruby and Rails.  I thought that ending a method with ! was a
>> naming convention.  Reading the humble ruby book it says "Another
>> convention to follow is that if the method modifies its receiver in
>> place (i.e. the method modifies the object that called it), then it
>> should end in an exclamation point" and the Rails doc show examples of
>> create without !
>> http://api.rubyonrails.org/classes/ActiveRecord/Ba... but if
>> I make the change you suggest the test passes.  I've updated the
>> tutorial and my code, but I'm confused.
>>
>
> The #create! method is documented here:
> http://api.rubyonrails.org/classes/ActiveRecord/Va...
>
> Essentially, #create will never raise an error no matter what you pass
> it,
> and you actually want exceptions for bad input in your tests (step
> definitions).
> Therefore - use #create! (or #save!). In your app, use the non-bang
> methods.

My Task model is simply defined (by the generate scaffold script) as:
class Task < ActiveRecord::Base
end

How is it that I can call Task.create! which is a method of
ActiveRecord::Validations ?

Thanks in advance,
Sarah
5f01846708cd8d474cae677fb20c786e?d=identicon&s=25 Caius Durling (Guest)
on 2008-12-22 20:31
(Received via mailing list)
_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users
0be0e4aa42aacd9a8a95c792de273ca7?d=identicon&s=25 Aslak Hellesøy (aslakhellesoy)
on 2008-12-22 20:31
(Received via mailing list)
On Mon, Dec 22, 2008 at 8:09 PM, Sarah Allen <lists@ruby-forum.com>
wrote:

> >> should end in an exclamation point" and the Rails doc show examples of
> >
>
> How is it that I can call Task.create! which is a method of
> ActiveRecord::Validations ?
>

Because ActiveRecord::Base includes the ActiveRecord::Validations
module.
It's not clear from the RDoc though...

>From active_record.rb:

ActiveRecord::Base.class_eval do
  extend ActiveRecord::QueryCache
  include ActiveRecord::Validations
  include ActiveRecord::Locking::Optimistic
  include ActiveRecord::Locking::Pessimistic
 ...lots more

Aslak
42172acdf3c6046f84d644cb0b94642c?d=identicon&s=25 Pat Maddox (pergesu)
on 2008-12-22 21:39
(Received via mailing list)
On Mon, Dec 22, 2008 at 11:29 AM, Caius Durling <caius@caius.name>
wrote:
> rescue_from handlers or within the controller actions themselves.
> rspec-users mailing list
> rspec-users@rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>

I'm a "use the non-bang methods in the app, bang methods in tests"
guy.  In the app, I don't want an exception to be raised, because
validation failures aren't exceptional.  if @post.save is good enough
to know what happened.  In tests though, I want it to fail fast and
noisily, so I use bang methods.

Pat
08fbedeb4ba773a4861c2537ee5c95d6?d=identicon&s=25 Steve Molitor (Guest)
on 2008-12-22 23:55
(Received via mailing list)
+1 @ Pat

I was going to respond in more detail, but I do exactly what Pat does --
bang in steps, no bang in Rails apps.  The Rails scaffolding boiler
plate
generates no bangs.
Steve
20ee0d23c969c7740d3c936a4675bb23?d=identicon&s=25 Sarah Allen (ultrasaurus)
on 2008-12-22 23:57
You guys are awesome.  For posterity, I've written up a bit about the
bang vs. non-bang as an aside in the tutorial:
http://www.ultrasaurus.com/code/2008/12/rails-2-da...

I'll have to read up on modules.  (I've only just finished ch 3 of the
humble ruby book.)

Oddly, I didn't see any content to the post by Caius Durling via
ruby-forum (
http://www.ruby-forum.com/topic/174015?reply_to=76... )

Warm regards and happy thank yous,
Sarah
5f01846708cd8d474cae677fb20c786e?d=identicon&s=25 Caius Durling (Guest)
on 2008-12-23 01:03
(Received via mailing list)
On 22 Dec 2008, at 22:57, Sarah Allen wrote:

> Oddly, I didn't see any content to the post by Caius Durling via
> ruby-forum (
> http://www.ruby-forum.com/topic/174015?reply_to=76... )


How weird, wonder if its because I signed the email with my GPG key.
Have sent this one unsigned so lets see if the content shows up for
this one...

C
---
Caius Durling
caius@caius.name
+44 (0) 7960 268 100
http://caius.name/
Cdf378de2284d8acf137122e541caa28?d=identicon&s=25 Matt Wynne (mattwynne)
on 2008-12-23 21:00
(Received via mailing list)
On 22 Dec 2008, at 19:09, Sarah Allen wrote:

> ActiveRecord::Validations ?
ActiveRecord::Validations uses a trick that's used widely in rails,
and is arguably[1] becoming a Ruby idiom, apparently.

This is the interesting bit, around line #275:

     def self.included(base) # :nodoc:
       base.extend ClassMethods

So basically that means that when the class ActiveRecord::Base
includes the module ActiveRecord::Validations, that module extends the
thing which included it (in this case ActiveRecord::Base) with the
class methods defined in ActiveRecords::Validations::ClassMethods.

Does that make sense?

I highly recommend reading David A Black's 'Ruby for Rails' at this
point in your learnings. It did me a world of good when I was
similarly new to Ruby. It's a really good deep grounding in Ruby IMO.

[1]http://blog.jayfields.com/2006/12/ruby-instance-an...

Matt Wynne
http://blog.mattwynne.net
http://www.songkick.com
3464536ce6396bacc132ad18d2c46489?d=identicon&s=25 Tim Walker (timw)
on 2008-12-24 00:12
(Received via mailing list)
Very nice indeed...


In your blog you said:

"Note that one of the steps is already defined in webrat. Isn't that
cool? As you get the hang of this, you reuse certain word patterns
which map to specific tests. But we're getting ahead of ourselves. We
need to dive into the creation of "steps" which make up our executable
spec. Cucumber gives a some handy snippets to get us started (in the
output of "rake features" above). We'll paste these into a new file
that we'll create in the "features/step_definitions" directory"

Why did one of the steps already get defined in webrat? Does it parse
"see" as indicative of UI? or what...?

Thanks very much.

Tim
0be0e4aa42aacd9a8a95c792de273ca7?d=identicon&s=25 Aslak Hellesøy (aslakhellesoy)
on 2008-12-24 00:42
(Received via mailing list)
On Wed, Dec 24, 2008 at 12:10 AM, Tim Walker <walketim@gmail.com> wrote:

> output of "rake features" above). We'll paste these into a new file
> that we'll create in the "features/step_definitions" directory"
>
> Why did one of the steps already get defined in webrat? Does it parse
> "see" as indicative of UI? or what...?
>

I try to only use magic when reality doesn't work ;-)
When you run "script/generate cucumber" you get a webrat_steps.rb file
that
contains these common steps.

Aslak
3464536ce6396bacc132ad18d2c46489?d=identicon&s=25 Tim Walker (timw)
on 2008-12-24 00:58
(Received via mailing list)
Ahh...reality is overrated.

Thanks again for your help guys. Making a lot of sense. If I could get
rcumber working that's be awesome.

Tim

On Tue, Dec 23, 2008 at 4:39 PM, aslak hellesoy
20ee0d23c969c7740d3c936a4675bb23?d=identicon&s=25 Sarah Allen (ultrasaurus)
on 2008-12-24 03:26
Matt Wynne wrote:
> ActiveRecord::Validations uses a trick that's used widely in rails,
> and is arguably[1] becoming a Ruby idiom, apparently.
>
> This is the interesting bit, around line #275:
>
>      def self.included(base) # :nodoc:
>        base.extend ClassMethods
>
> So basically that means that when the class ActiveRecord::Base
> includes the module ActiveRecord::Validations, that module extends the
> thing which included it (in this case ActiveRecord::Base) with the
> class methods defined in ActiveRecords::Validations::ClassMethods.
>
> Does that make sense?

um, no.  You say that the class ActiveRecord::Base includes the module
ActiveRecord::Validations, but I don't see that in the code I'm looking
at here:
http://dev.rubyonrails.org/browser/branches/2-0-st...

If I assume that I'm looking at the wrong code or it happens thru some
magic then you can make a module which will add its class methods to the
class which includes it?  Is that some kind of trick to create multiple
inheritance?  Is there any way without digging thru source to know which
class include methods from other classes or do y'all just get so cozy
with every Rails class you use that you "just know?"

> I highly recommend reading David A Black's 'Ruby for Rails' at this
> point in your learnings. It did me a world of good when I was
> similarly new to Ruby. It's a really good deep grounding in Ruby IMO.

Just ordered a second-hand copy online.  Thanks for the recommendation.

> [1]http://blog.jayfields.com/2006/12/ruby-instance-an...
Nice reference, but I didn't fully follow that either and posted a
similar question there.

Sarah

p.s Good question Tim on the webrat magic.  I added a note to the
tutorial that explains where the step was defined.
6cec982d39aac63fb41bdefdedf5e02c?d=identicon&s=25 Jeremiah Heller (Guest)
on 2008-12-24 08:10
(Received via mailing list)
On 23 Dec 2008, at 18:26, Sarah Allen wrote:

>> includes the module ActiveRecord::Validations, that module extends
> 
http://dev.rubyonrails.org/browser/branches/2-0-st...
Try here:
http://dev.rubyonrails.org/browser/branches/2-0-st...
On line 42: require 'active_record/validations'

> If I assume that I'm looking at the wrong code or it happens thru some
> magic then you can make a module which will add its class methods to
> the

> class which includes it?

I believe that's how modules work, but it's not by magic. If I'm
reading this Ruby book (by the Pragmatic Programmer's) here correctly
then Ruby creates a singleton class of the object calling extend
(which I think is the reasoning behind the code referenced by Matt),
then includes the module into that singleton class, which adds the
instance methods of the module into the superclass chain for that
object's class.

>  Is that some kind of trick to create multiple
> inheritance?  Is there any way without digging thru source to know
> which
> class include methods from other classes or do y'all just get so cozy
> with every Rails class you use that you "just know?"

The Ruby classes Module and Object have some methods to determine
other included modules, available public|private|protected methods,
etc. if that helps.

Perhaps someone more experienced can fill in any gaps I may've missed
- just happened to be reading about this myself...

Jeremiah
6cec982d39aac63fb41bdefdedf5e02c?d=identicon&s=25 Jeremiah Heller (Guest)
on 2008-12-24 08:14
(Received via mailing list)
On 23 Dec 2008, at 23:07, Jeremiah Heller wrote:

>>>
>> ActiveRecord::Validations, but I don't see that in the code I'm
>> looking
>> at here:
>> 
http://dev.rubyonrails.org/browser/branches/2-0-st...
>
> Try here: 
http://dev.rubyonrails.org/browser/branches/2-0-st...
> On line 42: require 'active_record/validations'

oops... line 59 looks useful as well: include ActiveRecord::Validations
Cdf378de2284d8acf137122e541caa28?d=identicon&s=25 Matt Wynne (mattwynne)
on 2008-12-24 10:41
(Received via mailing list)
On 24 Dec 2008, at 02:26, Sarah Allen wrote:

>> includes the module ActiveRecord::Validations, that module extends
> 
http://dev.rubyonrails.org/browser/branches/2-0-st...
You almost got it. Try here instead:
http://dev.rubyonrails.org/browser/branches/2-0-st...

> If I assume that I'm looking at the wrong code or it happens thru some
> magic then you can make a module which will add its class methods to
> the
> class which includes it?

Yes, that's basically what the self.included trick does. As I say,
it's debatable whether this is a neat trick or a horrible hack. If you
were reading the code that included the module,. might have only
expected that would add instance methods, rather than class methods as
well.

> Is that some kind of trick to create multiple
> inheritance?

Not really in that particular case. Ruby modules generally allow you
to do multiple inheritance by 'mixing in' behaviour to classes, but
that would be when you use 'include' to bring the methods defined in
the module into the class itself.

> Is there any way without digging thru source to know which
> class include methods from other classes or do y'all just get so cozy
> with every Rails class you use that you "just know?"

If you have hold of a class in ruby, there are ways to ask it what
modules / classes it inherits from, but I can't remember them off the
top of my head, sorry. Try messing around in irb for this kind of thing.

Matt Wynne
http://blog.mattwynne.net
http://www.songkick.com
48641c4be1fbe167929fb16c9fd94990?d=identicon&s=25 Mark Wilden (Guest)
on 2008-12-24 16:27
(Received via mailing list)
On Wed, Dec 24, 2008 at 1:32 AM, Matt Wynne <matt@mattwynne.net> wrote:


> Is that some kind of trick to create multiple
>> inheritance?
>>
>
> Not really in that particular case. Ruby modules generally allow you to do
> multiple inheritance by 'mixing in' behaviour to classes, but that would be
> when you use 'include' to bring the methods defined in the module into the
> class itself.


When you inherit from a class, you inherit both its instance methods and
its
class methods. When you include a module, you (usually) just inherit its
instance methods. The trick under discussion just makes sure you inherit
the
modules "class methods" as well, making it as if you inherited normally.

Is there any way without digging thru source to know which
> class include methods from other classes or do y'all just get so cozy
> with every Rails class you use that you "just know?"
>

ancestors tells you a class's superclasses (including modules).

///ark
0fff46f7ce00996fce5a32df1dc965d8?d=identicon&s=25 Vin MR (tvin_98)
on 2011-11-16 18:34
I'm new with Ruby and Cucumber.  I've tried this simple test, but it
didn't work for me

Given ....
When I enter ABC on keyboard
Then ...


And here is the ruby code
When /^I enter "([^\"]*) on keyboard$/ do |input|
.....
end



I always get a complain when executing the test
"You can implement step definitions for undefined steps with there
snippets:

When /^I enter ABC on keyboard$/ do
  pending # express the regexp above with the code you wish you had
end
"

And the code above was not executed.


Can anyone tell what I've done wrong here?

Thanks.
8133ee52ca72188132b5c7d97dfb967f?d=identicon&s=25 Chris Habgood (chabgood)
on 2011-11-16 18:49
(Received via mailing list)
this group is for rspec
5d38ab152e1e3e219512a9859fcd93af?d=identicon&s=25 David Chelimsky (Guest)
on 2011-11-16 19:32
(Received via mailing list)
On Nov 16, 2011, at 11:34 AM, Vin MR wrote:

> I'm new with Ruby and Cucumber.  I've tried this simple test, but it
> didn't work for me

Please send this to the Cucumber mailing list:
http://groups.google.com/group/cukes

Cheers,
David
0be0e4aa42aacd9a8a95c792de273ca7?d=identicon&s=25 Aslak Hellesøy (aslakhellesoy)
on 2011-11-16 19:36
(Received via mailing list)
On Wed, Nov 16, 2011 at 5:34 PM, Vin MR <lists@ruby-forum.com> wrote:
> I'm new with Ruby and Cucumber.  I've tried this simple test, but it
> didn't work for me
>
> Given ....
> When I enter ABC on keyboard
> Then ...
>
>
> And here is the ruby code
> When /^I enter "([^\"]*) on keyboard$/ do |input|

That RegExp doesn't match your step. This will match:

/^I enter (.*) on keyboard$/

Aslak
0be0e4aa42aacd9a8a95c792de273ca7?d=identicon&s=25 Aslak Hellesøy (aslakhellesoy)
on 2011-11-16 22:12
(Received via mailing list)
On Wed, Nov 16, 2011 at 5:45 PM, Chris Habgood <chabgood@gmail.com>
wrote:
> this group is for rspec
>

The Cucumber  list -> http://groups.google.com/group/cukes
This topic is locked and can not be replied to.