Posted by: rusteddev | November 30, 2010

Behavior Driven Development : Testing Nifty Authentication with Cucumber and Capybara

Today’s post is about Behaviour Driven Development. I’ll try to show you how to proceed with BDD on a basic feature : authentication. For this I’ll use  two helpers :

  • Nifty Authentication, one of the Nifty generators provided by Ryan Bates (you’ll probably know him and his popular RailsCast). It’s very simple to use and implements some good practices : crypted password, password confirmation, etc…
  • Cucumber, a Testing Framework that helps you define and run automated functional tests using plain text (User Stories like features description and Acceptance Test like scenarios).

Let’s begin :

  1. Set up the environment :
  2. Generate your rails 3 app, I’ll call mine bdd :

    rails new cuketest
    

    Then edit your Gemfile file to add the required gems, add the following lines :

    gem 'nifty-generators'
    group :development, :test do
     gem 'cucumber'
     gem 'cucumber-rails'
     gem 'rspec'
     gem 'rspec-rails'
     gem 'capybara'
     gem 'database_cleaner'
     gem 'launchy'
    end
    

    then let rails do the magic and install the missing gems :

    bundle install
    

    After that you need to configure your app to run cucumber, we’ll use capybara and rpsec framework to execute our cucumber tests.

    rails generate cucumber:install --capybara --rspec
    

    Ok, enough config, let’s move to code …. hum…. no …. to TEST !

  3. Describe the behavior :
  4. Create a new .feature file in the /feature directory. It will contain a description of the authentication feature and a test scenario. Let’s call it authentication.feature. The feature is described like User Stories in Scrum : In order to <purpose> As a <user> I want to <description_of_feature> The text is just for information. For  scenario, it’s a little bit different, it is still described in natural language but it’ll be interpreted by Cucumber to actually test the behavior. The scenario is described using this pattern Given <Before_situation> When <Action_tested> Then <Resulting_situation> This is the feature and scenario we want to test :

    Feature: Authentication
      In order to use bdd app
      As a visitor
      I want to be able to log in
    
    Scenario: Login
      Given I am not logged in
      When I go to the signup page
      And I fill in "user_username" with "user"
      And I fill in "user_email" with "user@gmail.com"
      And I fill in "user_password" with "passwd"
      And I fill in "user_password_confirmation" with "passwd"
      And I press "Sign up"
      Then I should see "You are now logged in."
    

    Now let’s try it : run the test with cucumber and see what happens….

    cucumber features -P
    

    Guess what ? It fails…. how else could it be, we didn’t code anything.Cucumber Feature Test : undefined step

    You can see from the output that cucumber found a scenario and executed it, but failed on first step “Given I’m not logged in” saying “undefined” step. We should tell cucumber how to be sure we are not logged. We’ll need to define a custom step.

  5. Define the steps :
  6. Go to the folder features/step_definitions and create a new file called authentication_steps.rb. Add dthe following content :

    Given /^I am not logged in$/ do
    visit("/logout")
    assert page.has_content?('You have been logged out.')
    end
    

    Test failed: great we can now code the logout !

    Now the color changed, it’s not brown anymore, it’s red. From undefined the step “Given I’m not logged in” is now defined and test failed. Other steps are still skipped.

    We must now code the step in order to logout.

  7. Code the feature :
  8. To deal with authentication we use nifty generators. We add the following line in the Gemfile :

    gem 'nifty-generators'
    

    Now we call the generator to create

    <pre>rails g nifty:layout
    rails g nifty:authentication
    

    OK ! well done, with this 2 lines you’ve done a pretty good work :

    with the first you created a simple css, application layout

    with the second authentication models, views, controllers, migrations, tests and configured Gemfile and routes. Everything needed to run a nice login and register feature.

    It’s almost done.

    Just execute migration and clone the dev to the test database :

    rake  db:migrate
    rake db:test:clone
    

    As we don’t want to see the default ruby home page, we should remove public/index.html and redefines route. Uncomment the following line of config/routes.rb and generate welcome controller

    root :to => "welcome#index"
    
    rails g controller welcome index
    

    Now run “rails server“, open you favorite web browser on http://localhost:3000 and try /login /logout.

    Ok now run again :

    cucumber features -P
    

    See the difference, now it’s all green ! Well done !

    Cucumber test all green : Great ! now Refactor

    In fact, it was a little bit to easy because we used nifty and everything run out green quite quickly (I helped a bit…). In the real world, they can be many failed attempts before all turns green.

That’s how Test Driven Development – TDD works :

  1. Define the test
  2. Make it fail : RED
  3. Make it run : GREEN (might take some time…)
  4. Refactor : optimize code and be sure to keep the test green.

So now go on and continue with Refactoring. It’s god time to optimize your code, make it clean and readable.  The test that took some time is now a good help, because running the simple “cucumber features -P” you’re it’s still working.

When you’re done try creating a new feature test (to check the password has min 4 characters). See it fail and enjoy seeing it turn to green.

Repeat and fade…..

Cucumber is great because this it’s behavior testing. Enough of boring Unit tests. You test the whole thing from database, to user interface and web sessions. You test what your customer really wants to see working. It’s not linked to the technical implementation. Who cares you coded this function using lists or hash tables, what does it change from a customer point of view ?

Cucumber is very easy to understand, you can even write tests side by side with your Product Owner. Existing steps using capybara are great and can be easily extended with custom steps to test everything.

That’s the end of my post. Go on with TDD and BDD, Cucumber is good for you !

Advertisements

Responses

  1. “let rails do the magic and install the missing gems” should be “let *bundler* ..”. The way you worded it mistakenly gives the impression that you don’t know what you’re talking about

    • My bad, yeah it’s bundler.. not rails

  2. “Behavior Driven Development : Testing Nifty Authentication
    with Cucumber and Capybara | Rusteddev’s Blog” ended up being a good article. If solely there were far more blogs similar to this one on the cyberspace. Regardless, thanks for ur time, Jeremiah


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: