Thursday, January 17, 2008

RSpec User Story example

Today, just a quick example showing what kind of wonderful things you can do with the new RSpec and its support for executable User Stories, a feature I was dreaming about for years...

Specification as a user story:



Story: Creating an order

Scenario: admin user creates an order
Given an admin user
And some orders
And some customers

When he creates an order

Then a new order is created
And a new customer is created

Implementation of the user story



Given "an admin user" do
login_as_admin
end

Given "some orders" do
@orders_count = Order.count
end

Given "some customers" do
@customers_count = Customer.count
end

When "he creates an order" do
post '/orders/create',
"order"=>{"address_attributes"=> {"name"=>"Customer 1"}}
end

Then "a new order is created" do
Order.count.should == @orders_count + 1
end

Then "a new customer is created" do
Customer.count.should == @customers_count + 1
end

The output when the user story is run:



Running 1 scenarios

Story: Creating an order

Scenario: admin user creates an order

Given an admin user
And some orders
And some customers

When he creates an order

Then a new order is created
And a new customer is created

1 scenarios: 1 succeeded, 0 failed, 0 pending

12 comments:

Fuzzyman said...

Hmmm... it looks to me like *executing* the test generates the user story - which isn't quite the same thing as an executable user story...

Andrzej Krzywda said...

Fuzzyman,

The first part is what you actually write. When you execute it (with a call to 'run' method which isn't shown here), it fails because you don't implement the steps.
In an additional file you define "steps" which are helpers for the user story (that's the second part which I call the implementation of a user story).

The description on the official RSpec webpage might be more clear:
http://rspec.info/

Fuzzyman said...

So the top paragraph is valid Ruby? That is interesting...

Kamil Dworakowski said...

Encourages abstraction, looks appealing.

jeffbski said...

And one of the cool parts is that when you parameterize your stories, then you can simply write new text stories that execute this existing code in different ways.

So you write a story, implement the pieces, parameterize to make reusable, and then write a bunch more stories with different parameters that exercise all this code.

Oliver said...

Hi,

thanks for the update on RSpec. Maybe I finally found a place where someone can explain to me what I actually gain from using RSpec ? While I do understand what you are doing above technically. I do not get the very basic concept why it's useful.

Because I do not get what is gained by proving this very simple, abstracted "outline" of the functionality you want to implement does indeed work. Of course, If I create an order, an order is created - why do I need to prove that to myself over and over again?

Because, after all, all the "boring" stuff is still left to, Rspec doesn't magically implement the whole thing for me, or does it?

So, is it only to prove basic things like 1 + 1 is indeed 2 (I am exaggerating), but then I do not understand why everybody is so exited about it. Same goes for Testdriven development in Rails - I did read the explanation in Agile Web Dev. with Rails, but what is gained from proving that super-simple abstraction of my functionality work, is beyond me..

Please enlighten me!

Thanks
Oliver

Emmanuel said...

Oliver:

>thanks for the update on RSpec. Maybe I >finally found a place where someone can >explain to me what I actually gain from >using RSpec?

What you gain is a specification that is closer to english of what your code _should_ do. RSpec also provides many helpers (like mock_model) that are very helpful when spec'ing your code.

>Of course, If I create an order, an >order is created - why do I need to >prove that to myself over and over >again?

First, you get to know that the code you test involves an order. Second, what happens if even this simple test fails? This can happen, and having a spec failing because of that can be very helpful to avoid looking for the bug in the wrong place.

>I do not get what is gained by proving >this very simple, abstracted "outline" >of the functionality you want to >implement does indeed work.

If you ask the developer (who might yourself :) what the code you are spec'ing was supposed to accomplish, he will not answer:

"order= Order.new; order.customer << Customer.find(:first, :condition => "sql condition"); ..."

No, he will answer: "First I create and order, then I look for the right user to assign it bla bla bla".

Thus, I think what you get is a more conversational description of the code, along with error checking of that description.

This is only mi view here, but I think the advantages of literate programming can be used as support for RSpec (and user stories also).

http://en.wikipedia.org/wiki/Literate_programming

Andrzej Krzywda said...

Oliver:

Thanks for asking about TDD/BDD.

It's not easy to answer your questions in a comment. I'm preparing another blog post to cover the reasons why I use BDD and what I gain from that.

Literate_programming, as mentioned by emmanuel (Thanks!), is one of the reasons I use RSpec.

BilloBallo said...

Andrzej and all the others,

thank you for the explanations. I think I can understand your reasoning on TDD / BDD and I can imagine scenarios where it could be useful in the very very beginning of thinking of a new application.

It seems to be useful when you do not have the slightest idea what your application has to consist of and what needs to be done.

Say, I want to "make an internet shop", so I have to have products, customers, a shopping cart, and a checkout.

Of course it's important to think about exactly what you need to have and how the parts work together, but what I learned and use on a daily basis is planning these things with pen and paper (making diagrams, etc.)

Now, If I understand right, BDD / TDD is doing the same thing but by code, or am I totally wrong?

For me, going from pen and paper to code seems awkward, as I giving up a lot of flexibility (I can't just draw arrows from a to b, strike out bad ideas, etc. like I could on a huge sheet of paper.

So, actually, it seems a lot more tedious for me to do BDD / TDD than planning on paper (or in a project application if you must), because if I do BDD / TDD, I get the benefit of tests, but these tests only test the very very basic functionality (which needs not to be questioned if planned right on paper). TDD / BDD doesn't save you from all the errors that will be introduced later when you start going from basic to actually implementing.

I am still curious about BDD / TDD as it's still a bit of a mystery to me, but I don't see a place for it between the planning of a software project and the actual, down and dirty implementation.

Maybe I am getting it wrong totally, so I am looking forward to your next blog posting.

Thanks.
Oliver

Andrzej Krzywda said...

Oliver,

I have posted an article on what I gain from TDD and BDD:

http://andrzejonsoftware.blogspot.com/2008/01/what-do-i-gain-from-tdd-or-bdd.html

Tell me if it answers your questions.

tomfmason said...

@Oliver

It sounds to me like you are used to a more plan driven or predictive development style. Whereas, with rspec, Agile or XP development methodologies are better suited.

There are many advantages to BDD and Agile or XP methodologies. IMO the biggest advantage is the extreme flexibility of the developer developing the application. They should be able to deal with rapidly changing/evolving specifications.

>these tests only test the very very basic functionality

I see this as a positive thing. A decent analogy would be building a foundation for a house of cement blocks. These blocks are really nothing by them selves but added together they form a very sturdy foundation.

>which needs not to be questioned if planned right on paper

It is nearly impossible to plan for every eventuality and if you try you will only waste your time. However, with Agile/XP development methodologies, changes and challenges are welcome. All you have to do is write a "test" and then write just enough code to make it pass.

So in the end you walk away with an application that is more easily extended and documented.

mhennemeyer said...

Hi,
i've written a short

blog series about developing rspec stories step implementations with bdd


Matthias