Rails 3 Cucumber / Machinist Tutorial: Machinist with Cucumber in 10 minutes
Erwin was kind enough to update my cucumber and machinist tutorial for Rails 3. This should be really useful for people who want to use cucumber to test with Rails 3. He notes that this is current with Rails3.rc and ruby 1.9.2.rc.1.
You can find his full repo here.
Rails 3 cucumber tutorial
So, here’s how to start using machinist with cucumber in a rails 3 app. I’ll use a simple app that deals with strawberries.
Start a rails app
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# sudo gem install rails --pre --source=http://gems.rubyonrails.org # or use rvm to test Rails 3 rails new strawberries cd strawberries # install http://github.com/ryanb/nifty-generators #To use Nifty Generators with Rails 3 you will need to include it in your Gemfile. gem "nifty-generators" rails g nifty:layout # other generators : nifty:scaffold, nifty:config, nifty:authentification |
Add them to your Gemfile, so that other folks on your team can easily get them.
1 2 3 4 5 6 7 8 9 10 11 |
gem 'database_cleaner' gem 'cucumber-rails' gem 'cucumber' gem 'rspec-rails' gem 'spork' gem 'launchy # so we can use : Then show me the page gem 'machinist', '>= 2.0.0.beta1' gem 'faker' |
1 2 3 4 5 6 7 8 |
#Then install the gems by running: bundle install # generate schema rake db:migrate # or alter /config/boot.rb if you do not intend to use a database |
Generate the files
From your rails app’s root, enter:
1 2 3 4 5 6 7 8 9 |
rails g cucumber:install --capybara rails g machinist:install touch features/support/blueprints.rb # add this line in it require 'machinist/active_record' |
Write a story
Now that we have our environment setup, let’s add the stories. These are just sketches of how our app should behave.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@wip : cucumber tag for work-in-progress
# features/strawberries.feature
Feature: Live
In order to live
people
want to be able to eat strawberries
@wip
Scenario: Eating strawberries
Given a strawberry that is "blue"
When I go to the homepage
Then I should see "There is 1 strawberry"
When I follow "eat the blue strawberry"
Then I should see "Strawberry eaten!"
|
Implement steps
It’s a good idea to implement steps first, so that you can have failing steps to work with. Cucumber will provide step definitions for us, so just enter:
1 2 3 |
rake cucumber:wip |
Now we can add the step definition for the strawberries.
1 2 3 4 5 6 7 8 |
#features/step_definitions/strawberry_steps.rb Given /^a strawberry that is "(.*)"$/ do |color| Strawberry.make!(:color => color) end |
Now let’s try rake cucumber:wip This time we get
1 2 3 4 |
1 uninitialized constant Strawberry (NameError) |
Which means it’s time to start adding code.
Implement feature and add blueprints</h3
Now that we’ve written some tests, we can go ahead and build this.
1 2 3 4 |
rails g nifty:scaffold strawberry color:string rake db:migrate |
Again, I’m using the nifty generator, which saves lots of time for making quick demo apps. Also, we’re going to want to add a strawberry blueprint, so that we can use Machinist. So, again, let’s try
1 2 3 4 |
rake cucumber:wip # => No master blueprint defined for class Strawberry |
This time we get No blueprint for class Strawberry (RuntimeError). So, let’s add a blueprint:
1 2 3 4 5 6 7 |
#features/support/blueprints.rb Strawberry.blueprint do color {Faker::Lorem.words(1).first.downcase} end |
This gives us the ability to say Strawberry.make, which will create a new strawberry with a random color. The nice part about machinist is that we can do both Strawberry.make and Strawberry.make(:color => ’red’), which becomes really useful when you have a model with a lot of validations that you don’t want to have to specify every time. Machinist lets you focus on specifying only what’s important to the specific test. Now, at this point, since I used the nifty_scaffold gem, we just have to change some text to make the feature pass, and we’re done.
So, now that we have a blueprint, let’s try rake:features again. We get undefined method `root_path’ for # (NoMethodError).
So, to fix this, let’s add a root path and delete public/index.html.
1 2 3 4 5 |
# config/routes.rb root :to => "strawberries#index" |
And then try rake features again. This time we get:
1 2 3 4 5 |
Then I should see "There is 1 strawberry" # features/step_definitions/web_steps.rb:89
expected: /There is 1 strawberry/m,
got: "<! #etc etc
|
So, what’s happening here is that cucumber/webrat are going to our home page, but they aren’t finding the text that we wrote that we wanted to see in the story. So, let’s change it.
1 2 3 4 |
# app/views/strawberries/index.html
<h1>There is <%= "#{Strawberry.count}" -%> strawberry</h1>
|
Now if we try rake features again we get Could not find link with text or title or id “eat the blue strawberry” (Webrat::NotFoundError) So we add that link
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<h1>There is <%= "#{Strawberry.count}" -%> strawberry</h1>
<table>
<tr>
<th>Color</th>
</tr>
<% @strawberries.each do |strawberry| %>
<tr>
<td><%=h strawberry.color %></td>
<td><%= link_to "Show", strawberry %></td>
<td><%= link_to "Edit", edit_strawberry_path(strawberry) %></td>
<td><%= link_to " eat the #{strawberry.color} strawberry", strawberry,
:confirm => 'Are you sure?', :method => :delete %></td>
</tr>
<% end %>
</table>
|
If I try rake cucumber:wip again, I see that now only the last step is failing.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
Then I should see “Strawberry eaten!” # features/step_definitions/web_steps.rb
expected: /Strawberry eaten!/m,
000
So, let’s fix that too.
---RUBY
# app/controllers/strawberries_controller.rb
def destroy
@strawberry = Strawberry.find(params[:id])
@strawberry.destroy
flash[:notice] = "Strawberry eaten!" #change the flash
redirect_to strawberries_url
end
|
So, now we have 5 passing steps
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
…./strawberries$ rake cucumber:wip
Feature: Live
In order to live # features/strawberries.feature
people
want to be able to eat strawberries
Scenario: Eating strawberries # features/strawberries.feature:5
Given a strawberry that is "blue" # features/step_definitions/strawberry_steps.rb:2
When I go to the homepage # features/step_definitions/webrat_steps.rb:6
Then I should see "There is 1 strawberry" # features/step_definitions/webrat_steps.rb:89
When I follow "eat the blue strawberry" # features/step_definitions/webrat_steps.rb:14
Then I should see "Strawberry eaten!" # features/step_definitions/webrat_steps.rb:89
1 scenario
5 steps passed
|
Machinist note So, hopefully this is enough for you to get started with. The value of machinist really comes later, when you have a model with more than 1 field, and when you need to make a bunch without wanting to specify everything every time. For example:
1 2 3 4 5 6 7 |
User.blueprint do password {'password'} password_confirmation {'password'} name {Faker::Lorem.words(1).first} end |
Here, it would be annoying to have to specify the passwords each time, so it’s easier to let machinist do it, so that you can just say User.make!, or User.make!(:name => ’mischa’).
August 04, 2010

