Showing posts with label bdd. Show all posts
Showing posts with label bdd. Show all posts

Wednesday, May 21, 2008

Story Driven Development

If you are interested in testing and the TDD/BDD movements, then you may find Bryan Helmkamp presentation on "Story Driven Development" worth watching. Bryan explains the differences between unit testing and scenarios. He also shows Webrat, a tool he works on, which makes defining stories in Rails apps very easy.

I like the title that Bryan has chosen for the talk. The name "Story Driven Development" makes it clear that it's a lot about defining requirements, and not only about testing. Additionally, I think it's clear that it focuses on the acceptance level of tests without mentioning unit tests.

He also provides a quote from Robert Martin:

Unit tests: “Make sure you write the code right.”
Scenarios: “Make sure you write the right code.”

You can watch the slides here, or grab the PDF version (which has correct code examples).

Wednesday, April 2, 2008

BDD examples with user stories and Webrat

This is the best BDD explanation I have ever seen. It explains all the philosophy behind BDD, shows how it fits with RSpec stories, and how you can use Webrat to create a high-level integration test. It even shows how to use Selenium with RSpec stories!

Integration Testing in Ruby with RSpec's Story Automation Framework by David Chelimsky

Big thanks to David Chelimsky!

Monday, February 11, 2008

Andrzej's Rails tips #5

Two things today, both related to RSpec stories: webrat, and using regexps in RSpec stories.

Webrat with RSpec stories

What is Webrat? "Webrat lets you quickly write robust and thorough acceptance tests for a Ruby web application". It uses Hpricot under the hood and is very easy to understand just by looking at the code.

It took me only 30 minutes to turn most of my tests in one of my applications from a classic IntegrationTest-based RSpec story to Webrat. Here is one example:

When "he creates an order" do
visits '/'
clicks_link "New order"
fills_in "Nr", :with => 'abc/2008'
fills_in "Company", :with => 'ABC company'
selects 'New'
clicks_button 'Create'
end

Thanks to Ben, for his great article describing RSpec stories with Webrat.


RSpec, response.should have_text


Sometimes, all you need is just a check whether there is a certain message visible on a page. One way of doing that is with regexps. Here is an example step that checks for the message:


Then "he sees a $message" do |message|
response.should have_text(Regexp.new(message))
end

Monday, January 21, 2008

What do I gain from TDD or BDD?

The question what do I gain from doing TDD/BDD is asked quite often. I understand the reasons people ask for that. I have practised TDD since 2001. This post is an explanation of why I TDD/BDD and what I gain from it.

Why do I BDD?

BDD helps me with 3 aspects of software development: Design, Defense, Documentation.
  • Design
    • When I write the specifications(tests) first, I see that my design is simpler (as compared to write the code first) for given requirements, thus better.
      • I know it's not very intuitive, you just have to try it.
    • When you start with tests, your design is more testable.
      • It makes debugging easier.
    • TDD doesn't replace drawing diagrams.
      • It's just an additional design technique.
      • I still enjoy drawing UML-like diagrams!
  • Defense
    • I feel much safer having my application covered with tests, .
      • Thanks to that, I can do some refactoring when I feel it's needed, run the tests, and if it's 'green' I just check it in.
    • Whenever some of my users find any bug, I prepare a test that covers it.
      • Only then I fix the bug and release the change.
      • There's nothing worse than having a bug that reappears again (after fixing it) in the application.
  • Documentation
    • I'm not a fan of big Word documents that describe all details of the requirements.
      • It's just too difficult to synchronize this document with reality after every requirements change
        • Changes are inevitable.
      • There was one large project I was working on, where nobody from the team (including the project manager) knew what all the requirements were!
        • Yes, it is pathological.
    • I store all of the requirements as executable stories/tests.
      • Before releasing any change I run all the stories.
      • When there is a requirement change I just find the story responsible for that, change it appropriately and change the code.
        • Changes are inevitable.
Do I have to TDD/BDD in order to be successful?

Well... No.

I know some very good developers that don't write any tests and are successful. There are other ways of ensuring good design or documentation. As for defense, you may have a very fast testing department that makes sure you didn't break anything. Or maybe you just prefer to manually go through your application. For me it's just too slow,
I prefer an immediate response that is free of any human mistakes. Chances are, you are just so perfect that you don't introduce any breaking changes. Lucky you!

It's also possible that you separate the analysis, design and implementation phases so strongly, that there is no way of changing anything during the implementation phase. I'm not a big fan of this approach but I know that many people are successful with that. I believe that even in this case you can gain a lot from writing acceptance tests (executable stories). Writing unit tests for your classes is also a good thing. I'll try to cover the topic of testing on different levels (acceptance, units) in a separate post.


But it's difficult and expensive, isn't it?

Yes, it is. All I gain doesn't come for free.

First of all, it requires discipline. It takes some time to get used to write tests first.
Also, it takes some time to learn how to do correct TDD/BDD. The good news is that you can start introducing it gradually.

Another thing is that after creating a lot of tests for your applications the whole suite may take some time to run. It's a problem that is not easy to solve, but believe me you'd prefer this kind of problems than a 5-days debugging session.

Is it fun?

Yes, it's a lot of fun!
Again, you have to try it before you know, what I'm talking about. If you're still new to TDD, look around, maybe there is someone experienced nearby who can show you a quick demo.

What next?

Find some TDD tools for your technology. I believe they exist for every programming language. Find a place in your application where you'd like to start testing. Start with something simple. Maybe assuring that a request to a given page is successful? Or maybe asserting that all the values in the Order class are calculated correctly? Make sure you run those tests after every change of your application.

Feel free to ask me questions about TDD or BDD. I have practised it with Java, C#, IronPython and Ruby. The technology doesn't matter too much in this case. You can use comments for that or simply email me at andrzejkrzywda at gmail.com.

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