{"id":599,"date":"2008-12-22T00:42:19","date_gmt":"2008-12-22T08:42:19","guid":{"rendered":"https:\/\/www.ultrasaurus.com\/sarahblog\/2008\/12\/rails-2-day-3-behavior-driven-development\/"},"modified":"2008-12-22T00:42:19","modified_gmt":"2008-12-22T08:42:19","slug":"rails-2-day-3-behavior-driven-development","status":"publish","type":"post","link":"https:\/\/www.ultrasaurus.com\/2008\/12\/rails-2-day-3-behavior-driven-development\/","title":{"rendered":"rails 2 day 3: behavior-driven development"},"content":{"rendered":"
Now that we have learned some basic Ruby syntax and gained some understanding about what the Rails generate scaffold script does, it is high time we started using a more modern approach to coding. In fact, if you recall at the end of day 2<\/a>, I realized with horror that we had actually modified code and added features without developing the tests first. This defied everything I had ever heard about good coding practices from the Ruby crowd and I set off to mend my ways.<\/p>\n Rick Denatale<\/a> describes the process of test-driven\/behavior-driven development as:<\/p>\n After reading a bit<\/a> about test- and behavior-driven development, I decided to use a relatively new framework called cucumber<\/a> which uses natural language to describe features.<\/p>\n Today we will:<\/p>\n <\/p>\n <\/p>\n h1 {font-size: 150%} <\/p>\n <\/a><\/p>\n Based on these install instructions<\/a><\/p>\n important<\/strong>: Cucumber 0.1.12 and up depends on Webrat 0.3.2.1 or higher, which as of this writing is not yet officially released to Rubyforge’s gem repository. In the meanwhile, install Bryan Helkamp’s snapshot gem:<\/p>\n The plugins’ dependencies must be installed separately:<\/p>\n <\/p>\n <\/p>\n <\/a><\/p>\n First we’ll create the Rails “to do list” application:<\/p>\n Now we’ll set up cucumber for the project<\/p>\n Just to make sure that everything is installed correctly:<\/p>\n If that runs without errors you are ready to rock.<\/p>\n <\/a><\/p>\n <\/p>\n <\/a><\/p>\n In the features directory that was auto-created for us with the cucumber script, we create a .feature file which starts with a description of the feature. The first section that describes the feature appears to be purely documentation; however the “scenario” sections will each become part of the executable feature definition. For starters we’ll do something simple.<\/p>\n We know we haven’t written any executable steps, but we’ll execute it anyhow:<\/p>\n Note that one of the steps is already defined in webrat. Isn’t that cool? When we set up cucumber for the project, it automatically includes step_definitions\/webrat_steps.rb which defines some common steps. 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:<\/p>\n Note that I touched up the first step to include a regular expression. This means I could add \n<\/p>\n <\/a><\/p>\n To create the task, I’m calling my Task model directly (since I’m new to Rails, I looked up the ActiveRecord::Base syntax in the Rails Framework API docs<\/a>). In my first pass I wrote:<\/p>\n However, Aslak Helles\u00f8y kindly pointed out<\/a> that it would fail silently with that syntax, and instead I should call <\/p>\n <\/a><\/p>\n Looking in Ok, now we have a simple spec. Is it time to write the code? No!<\/p>\n <\/p>\n <\/a> As expected, we see errors on our first step, since we have not yet written any code for the application.<\/p>\n <\/p>\n <\/a><\/p>\n Now, at last it is time to write code<\/p>\n Run the spec again..<\/p>\n \n It passes, yay!<\/p>\n <\/p>\n <\/a><\/p>\n When we first set up our app, to setup cucumber:<\/p>\n To describe our feature, we create two files:<\/p>\n To run the feature description:<\/p>\n Now that we have learned some basic Ruby syntax and gained some understanding about what the Rails generate scaffold script does, it is high time we started using a more modern approach to coding. In fact, if you recall at the end of day 2, I realized with horror that we had actually modified code… Continue reading \n
\n
\n
\nh1,h2 {font-style: bold}
\nimg
\n{
\nborder:2px solid silver;
\nmargin:0px 0px 15px 20px;
\n}
\nblockquote, pre.code {
\nborder: solid 1px #aaa;
\npadding: 6px;
\nbackground-color: #eee;
\ncolor: inherit;
\noverflow:auto;
\nmargin: 10px 0px;
\n}<\/p>\nInstall Cucumber<\/h1>\n
sudo gem install rspec rspec-rails cucumber webrat<\/pre>\n
\ngem sources -a http:\/\/gems.github.com\nsudo gem install brynary-webrat\n<\/pre>\n
\ngem install term-ansicolor treetop diff-lcs nokogiri\n<\/pre>\n
Setup the Application<\/h1>\n
\ncd $webroot\nrails -d mysql todolist\ncd todolist\nrake db:create:all\nrake db:migrate\n<\/pre>\n
\nruby script\/generate cucumber\ncreate features\/step_definitions\ncreate features\/step_definitions\/webrat_steps.rb\ncreate features\/support\ncreate features\/support\/env.rb\nexists lib\/tasks\ncreate lib\/tasks\/cucumber.rake\ncreate script\/cucumber\n<\/pre>\n
rake features<\/pre>\n
Describe a Feature<\/h1>\n
features\/tasklist.feature<\/strong><\/code><\/p>\n
\nFeature: Tasks\nIn order to keep track of tasks\nPeople should be able to\nCreate a list of tasks\n\nScenario: List Tasks\nGiven that I have created a task \"task 1\"\nWhen I go to the tasks page\nThen I should see \"task 1\"\n<\/pre>\n
<\/p>\n
features\/step_definitions\/tasklist_steps.rb<\/strong><\/code><\/p>\n
\nGiven \/^that I have created a task \"(.*)\"$\/ do |desc|\nTask.create!(:description => desc)\nend\n\nWhen \/^I go to the tasks page$\/ do\nvisit \"\/tasks\"\nend\n<\/pre>\n
Given that I have created a task \"foo\"<\/code> to another scenario and it would match this step.<\/p>\n
Short aside on task creation syntax<\/h2>\n
\ntask = Task.new(:description => desc);\ntask.save\n<\/pre>\n
task.save!<\/code> or the even simpler
Task.create!(:description => desc)<\/code>. I had missed create! in the documentation, since it is part of ActiveRecord::Validations<\/a>. The API doc is a little confusing on this point, but looking at the source shows that ActiveRecord::Validations is included as a module<\/a>. Pat Maddox notes<\/a> that he uses the bang version (.save!) in tests, and the non-bang version (.save) in production code since validation errors aren’t exceptional.<\/p>\n<\/blockquote>\n
Back to Step 3<\/h2>\n
features\/step_definitions\/webrat_steps.rb<\/code>, you can see the definition of our third step:<\/p>\n
\nThen \/^I should see \"(.*)\"$\/ do |text|\nresponse.body.should =~ \/#{text}\/m\nend\n<\/pre>\n
Execute the Feature and Watch it Fail<\/h1>\n
\n<\/p>\n
Write the code to make it pass<\/h1>\n
\n$ .\/script\/generate scaffold Task description:string\n$ rake db:migrate\n<\/pre>\n
<\/p>\n
What did we learn?<\/h1>\n
\nruby script\/generate cucumber\n<\/pre>\n
\n
\nrake features\n<\/pre>\n","protected":false},"excerpt":{"rendered":"