SlideShare uma empresa Scribd logo
1 de 27
Baixar para ler offline
RSpec and User Stories
              A step by step tutorial
                By Rahoul Baruah
            http://www.brightbox.co.uk



   Released under the Creative Commons Attribution Share-Alike Licence
What is RSpec?
 Behaviour Driven Development
 An evolution of Test Driven Development
 Concentrates on the “behaviour” of your
  system
 Specify the behaviour first, implement it
  second, refactor it third.
What are User Stories?
 Acceptance Tests for RSpec
 Describe the functionality of your application
  in terms your customer will understand
 Prove that the application does what it is
  supposed to.
A Simple Authentication System
   Write the feature
   Write verification code for the feature
   Specify the controller
   Implement the controller
   Specify the models
   Implement the models
   Verify the feature works as required
   Refactor
Write our Feature
 Write our feature and save it as features/
  allow-a-user-to-login.feature
 Show it to the customer and have it approved
 Run rake features
 Feature: Allow a User to log in
    As a user,
    I want to log in,
    So I can see my stuff
    Scenario: Successful login
          Given a user called Dave with a password of secret
          And 15 items of stuff
          When I log in as Dave with password secret
          Then I should see the Dashboard page
          And it should list my 15 items of stuff
    Scenario: Unsuccessful login
          Given a user called Dave with a password of secret
          When I log in as Dave with password potato
          Then I should see the Login page
          And I should see a message saying “an incorrect username or
           password was supplied”
rake features
 When we run ‘rake features’ it tells us that
  none of the features are implemented
 So we start with the first step and implement
  that
Steps - proving a feature works
 Create Ruby files, registration-steps.rb and
  session-steps.rb, in features/steps
 These contain the code verifying that the
  feature works as expected
registration and session steps
Given /^a user called (.*) with a password of (.*)$/ do | username, password |
    user = User.find_by_username username
    user.destroy unless user.nil?
    visits '/registrations/new'
    fills_in 'User name', :with => username
    fills_in 'Password', :with => password
    fills_in 'Password Confirmation', :with => password
    clicks_button 'Register'
end


When /^I log in as (.*) with password (.*)$/ do | username, password |
    visits '/sessions/new'
    fills_in 'User name', :with => username
    fills_in 'Password', :with => password
    clicks_button 'Log in'
end


Then /^I should see the Dashboard page$/ do
    response.should redirect_to('/dashboard')
end


     Use Webrat to define our interactions with the application
     Use RSpec to check the responses from the application
Specify our Controller
   ‘rake features’ fails
   So we need to start writing some code to make it pass
   But before we write any code, we need a specification
   So we run…
	 ruby script/generate rspec_controller Registrations

 …to build a blank controller and specification
 Now to implement the RegistrationsController.
 Similar work needs to be done with the
  SessionsController for actually logging in.
describe RegistrationsController do
  describe quot;GET newquot; do
    it quot;should show the form to allow someone to registerquot; do
      on_getting :new do
          expect_to_create_a_blank_user
      end
      response.should be_success
      response.should render_template('registrations/new')
    end


  describe quot;POST createquot; do
    it quot;should create and log in a new userquot; do
      on_posting_to :create, :user => { quot;somequot; => :values } do
          expect_to_build_a_new_user_with quot;somequot; => :values
          expect_to_save_the_new_user_successfully
      end
      controller.current_user.should == @user
    end


    it quot;should redirect to the users dashboardquot; do
      on_posting_to :create, :user => { quot;somequot; => :values } do
          expect_to_build_a_new_user_with quot;somequot; => :values
          expect_to_save_the_new_user_successfully
      end
Cont’d…

      it quot;should fail to create a new user if given invalid valuesquot; do
        on_posting_to :create, :user => { quot;somequot; => :values } do
            expect_to_build_a_new_user_with quot;somequot; => :values
            expect_to_fail_to_save_the_new_user
        end
        controller.current_user.should be_blank
      end


      it quot;should reshow the registration form if given invalid valuesquot; do
        on_posting_to :create, :user => { quot;somequot; => :values } do
            expect_to_build_a_new_user_with quot;somequot; => :values
            expect_to_fail_to_save_the_new_user
        end
        response.should render_template('/sessions/new')
        flash[:error].should == 'There were some errors when registering your details'
      end
 end
end
Specification for new registrations

 Use helper methods to make the specification easier to read
 Use mock objects so we are testing just the controller, not the
  (non-existent) models
 Note how we can supply quot;somequot; => :values for
  the :registration parameter. As we are not using real
  models, the actual fields do not matter; what counts is how
  the controller behaves in response to certain actions.
def expect_to_create_a_blank_user
    @user = mock_model User
    User.should_receive(:new).and_return(@user)
end


def expect_to_build_a_new_user_with parameters
    @user = mock_model User
    User.should_receive(:new).with(parameters).and_return(@user)
end


def expect_to_save_the_new_user_successfully
    @user.should_receive(:save!).and_return(true)
end


def expect_to_fail_to_save_the_new_user
    prepare_for_errors_on @user
    @user.should_receive(:save!).and_raise(ActiveRecord::RecordInvalid.new(@user))
end

     The helpers build a mock user
     We tell the mock to expect certain method calls and return the
      correct responses
Implement the Controller
 We do need to build a model…
	 ruby script/generate rspec_model User

 …so that our steps will run
 Remove the < ActiveRecord::Base from the definition for now
  (so that ActiveRecord does not complain about our lack of
  database tables)
 But we don’t implement anything in it yet; our controller
  specification is using mocks so does not actually need a real
  object
 We also need to add some routes to get things moving…
	   	   map.resources :registrations
	   	   map.resources :sessions
	   	   map.resource :dashboard
Implementing the Controller
class RegistrationsController < ApplicationController
  def new
      @user = User.new
  end


  def create
      @user = User.new params[:user]
      @user.save!
      redirect_to dashboard_path


  rescue ActiveRecord::RecordInvalid
      flash[:error] = 'There were some errors when registering your details'
      render :template => 'registrations/new', :status => 422
  end
end


 The implementation is pretty simple, which is exactly as it
  should be.
Specifying the Model
 Now we have our controller behaving as
  specified we need to specify the behaviour of
  our User model
 We have already generated the RSpec files, we
  just need to tell it how we expect a User to
  behave.
Specifying the Model
 We write the specs
 Update the migration to deal with the fields we
  need
 We switch the model back so that it descends
  from ActiveRecord::Base
 We run the migration
 We implement the model
Specifying the Model
First attempt…
describe User do
 it quot;should have a usernamequot; do
   @user = User.new :username => ''
   @user.should_not be_valid
   @user.should have(1).errors_on(:username)
 end


 it quot;should have a unique usernamequot; do
    @first_user = User.create! :username => 'arthur', :password =>
   '12345', :password_confirmation => '12345'


   @second_user = User.new :username => 'arthur'
   @second_user.should_not be_valid
   @second_user.should have(1).errors.on(:username)
 end


Cont’d…
Cont’d…

 it quot;should confirm the password before savingquot; do
      @user = User.new :password => 'secret', :password_confirmation => 'notsecret'
      @user.should_not be_valid
      @user.should have(1).errors_on(:password)
 end


 it quot;should encrypt the password before saving to the databasequot; do
      PasswordEncrypter.should_receive(:encrypt).with('12345').and_return('3ncrypt3d')


       @user = User.new :username => 'arthur', :password => '12345', :password_confirmation
      => '12345'
      @user.save!
      @user.encrypted_password.should == '3ncrypt3d'
 end
end
Specifying the Model
 There are two areas of the specification that “smell
  bad”
 Both “it should have a unique username” and “it should
  encrypt the password before saving to the database”
  require a valid object to be saved; which in turn
  require knowledge of the object beyond that individual
  specification clause
 Ideally this would not be necessary but is a problem
  with the ActiveRecord pattern; mixing business logic
  and persistence logic in a single class
 The (imperfect) solution is to use object
  ‘factories’ that encapsulate knowledge of a
  valid model.
 We are still spreading that knowledge outside
  of the specification but at least it is a single
  place to make that change (usually in spec/
  spec_helper.rb)
describe User do
 it quot;should have a usernamequot; do
   @user = a User, :username => ''
   @user.should_not be_valid
   @user.should have(1).errors_on(:username)
 end


 it quot;should have a unique usernamequot; do
   @first_user = a_saved User, :username => ‘arthur’


   @second_user = a User, :username => 'arthur'
   @second_user.should_not be_valid
   @second_user.should have(1).errors.on(:username)
 end


 it quot;should confirm the password before savingquot; do
   @user = a User, :password => 'secret', :password_confirmation => 'notsecret'
   @user.should_not be_valid
   @user.should have(1).errors_on(:password)
 end
 Rewritten to use “a Something” and “a_saved
  Something” as an object factory
 Each specification clause only specifies the
  information it needs.
 The factory ensures that the rest of the object
  is valid.
Acceptance
 By now we should have done enough to let the
  first step in our story pass its acceptance test
 rake features will prove it
 That should be all we need to do for that
  particular step - any extra development is
  unnecessary as it has not been requested by
  the customer
 However, we can now safely refactor the code,
  to organise it better, safe in the knowledge
  that we can prove that it still does what is
  required without breakages.
Appendix
 We have a fork of RSpec for Rails that provides a set of helper
  methods: prepare_for_errors_on, on_getting,
  on_posting_to, on_putting_to and on_deleting_from
 See http://github.com/rahoulb/rspec-rails/wikis/home
 We are working on an object factory that makes building
  models (without full knowledge of their internals) a bit
  simpler…

   Object.factory.when_creating_a User, :auto_generate
    => :username, :auto_confirm => :password
	   @user = a User
	   @user = a_saved User # as above but auto-saves the user
	   @user.should be_valid
 See http://github.com/rahoulb/object-factory/wikis (although
  at the time of writing, November 2008, this is not quite ready)
www.brightbox.co.uk
hello@brightbox.co.uk
twitter.com/brightbox

Mais conteúdo relacionado

Mais procurados

greach 2014 marco vermeulen bdd using cucumber jvm and groovy
greach 2014 marco vermeulen bdd using cucumber jvm and groovygreach 2014 marco vermeulen bdd using cucumber jvm and groovy
greach 2014 marco vermeulen bdd using cucumber jvm and groovyJessie Evangelista
 
Testing Ruby with Rspec (a beginner's guide)
Testing Ruby with Rspec (a beginner's guide)Testing Ruby with Rspec (a beginner's guide)
Testing Ruby with Rspec (a beginner's guide)Vysakh Sreenivasan
 
Intro to-rails-webperf
Intro to-rails-webperfIntro to-rails-webperf
Intro to-rails-webperfNew Relic
 
Rspec API Documentation
Rspec API DocumentationRspec API Documentation
Rspec API DocumentationSmartLogic
 
Introduction to testing in Rails
Introduction to testing in RailsIntroduction to testing in Rails
Introduction to testing in Railsbenlcollins
 
[Thong Nguyen & Trong Bui] Behavior Driven Development (BDD) and Automation T...
[Thong Nguyen & Trong Bui] Behavior Driven Development (BDD) and Automation T...[Thong Nguyen & Trong Bui] Behavior Driven Development (BDD) and Automation T...
[Thong Nguyen & Trong Bui] Behavior Driven Development (BDD) and Automation T...Ho Chi Minh City Software Testing Club
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the FinishYehuda Katz
 
Automated testing with RSpec
Automated testing with RSpecAutomated testing with RSpec
Automated testing with RSpecNascenia IT
 
Intro to Rails Give Camp Atlanta
Intro to Rails Give Camp AtlantaIntro to Rails Give Camp Atlanta
Intro to Rails Give Camp AtlantaJason Noble
 
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...Caldera Labs
 
Caldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW WorkshopCaldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW WorkshopCalderaLearn
 
Simplifying Code: Monster to Elegant in 5 Steps
Simplifying Code: Monster to Elegant in 5 StepsSimplifying Code: Monster to Elegant in 5 Steps
Simplifying Code: Monster to Elegant in 5 Stepstutec
 
What's new in Rails 2?
What's new in Rails 2?What's new in Rails 2?
What's new in Rails 2?brynary
 

Mais procurados (20)

greach 2014 marco vermeulen bdd using cucumber jvm and groovy
greach 2014 marco vermeulen bdd using cucumber jvm and groovygreach 2014 marco vermeulen bdd using cucumber jvm and groovy
greach 2014 marco vermeulen bdd using cucumber jvm and groovy
 
RSpec 2 Best practices
RSpec 2 Best practicesRSpec 2 Best practices
RSpec 2 Best practices
 
Testing Ruby with Rspec (a beginner's guide)
Testing Ruby with Rspec (a beginner's guide)Testing Ruby with Rspec (a beginner's guide)
Testing Ruby with Rspec (a beginner's guide)
 
Intro to-rails-webperf
Intro to-rails-webperfIntro to-rails-webperf
Intro to-rails-webperf
 
jQuery Intro
jQuery IntrojQuery Intro
jQuery Intro
 
Rspec API Documentation
Rspec API DocumentationRspec API Documentation
Rspec API Documentation
 
Introduction to testing in Rails
Introduction to testing in RailsIntroduction to testing in Rails
Introduction to testing in Rails
 
RSpec
RSpecRSpec
RSpec
 
I Love codeigniter, You?
I Love codeigniter, You?I Love codeigniter, You?
I Love codeigniter, You?
 
Rails is not just Ruby
Rails is not just RubyRails is not just Ruby
Rails is not just Ruby
 
Catalog display
Catalog displayCatalog display
Catalog display
 
[Thong Nguyen & Trong Bui] Behavior Driven Development (BDD) and Automation T...
[Thong Nguyen & Trong Bui] Behavior Driven Development (BDD) and Automation T...[Thong Nguyen & Trong Bui] Behavior Driven Development (BDD) and Automation T...
[Thong Nguyen & Trong Bui] Behavior Driven Development (BDD) and Automation T...
 
Excellent
ExcellentExcellent
Excellent
 
Rails 3: Dashing to the Finish
Rails 3: Dashing to the FinishRails 3: Dashing to the Finish
Rails 3: Dashing to the Finish
 
Automated testing with RSpec
Automated testing with RSpecAutomated testing with RSpec
Automated testing with RSpec
 
Intro to Rails Give Camp Atlanta
Intro to Rails Give Camp AtlantaIntro to Rails Give Camp Atlanta
Intro to Rails Give Camp Atlanta
 
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...
Single Page Web Apps As WordPress Admin Interfaces Using AngularJS & The Word...
 
Caldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW WorkshopCaldera Learn - LoopConf WP API + Angular FTW Workshop
Caldera Learn - LoopConf WP API + Angular FTW Workshop
 
Simplifying Code: Monster to Elegant in 5 Steps
Simplifying Code: Monster to Elegant in 5 StepsSimplifying Code: Monster to Elegant in 5 Steps
Simplifying Code: Monster to Elegant in 5 Steps
 
What's new in Rails 2?
What's new in Rails 2?What's new in Rails 2?
What's new in Rails 2?
 

Destaque

RSpec and Rails
RSpec and RailsRSpec and Rails
RSpec and RailsAlan Hecht
 
RSpec: What, How and Why
RSpec: What, How and WhyRSpec: What, How and Why
RSpec: What, How and WhyRatan Sebastian
 
Introduction to ATDD with Cucumber and RSpec
Introduction to ATDD with Cucumber and RSpecIntroduction to ATDD with Cucumber and RSpec
Introduction to ATDD with Cucumber and RSpecKenta Murata
 
RSpec on Rails Tutorial
RSpec on Rails TutorialRSpec on Rails Tutorial
RSpec on Rails TutorialWen-Tien Chang
 
DevDay 2016: Dave Farley - Acceptance testing for continuous delivery
DevDay 2016: Dave Farley - Acceptance testing for continuous deliveryDevDay 2016: Dave Farley - Acceptance testing for continuous delivery
DevDay 2016: Dave Farley - Acceptance testing for continuous deliveryDevDay Dresden
 
software testing
 software testing software testing
software testingSara shall
 
Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013Brian Sam-Bodden
 
Unit testing best practices
Unit testing best practicesUnit testing best practices
Unit testing best practicesnickokiss
 
Unit Testing Concepts and Best Practices
Unit Testing Concepts and Best PracticesUnit Testing Concepts and Best Practices
Unit Testing Concepts and Best PracticesDerek Smith
 
Software Testing Life Cycle
Software Testing Life CycleSoftware Testing Life Cycle
Software Testing Life CycleUdayakumar Sree
 
An Overview of User Acceptance Testing (UAT)
An Overview of User Acceptance Testing (UAT)An Overview of User Acceptance Testing (UAT)
An Overview of User Acceptance Testing (UAT)Usersnap
 
React JS and why it's awesome
React JS and why it's awesomeReact JS and why it's awesome
React JS and why it's awesomeAndrew Hull
 
Software Testing Basics
Software Testing BasicsSoftware Testing Basics
Software Testing BasicsBelal Raslan
 
Introduction to Agile software testing
Introduction to Agile software testingIntroduction to Agile software testing
Introduction to Agile software testingKMS Technology
 
Software Testing Fundamentals
Software Testing FundamentalsSoftware Testing Fundamentals
Software Testing FundamentalsChankey Pathak
 
Software testing basic concepts
Software testing basic conceptsSoftware testing basic concepts
Software testing basic conceptsHưng Hoàng
 

Destaque (18)

RSpec and Rails
RSpec and RailsRSpec and Rails
RSpec and Rails
 
RSpec: What, How and Why
RSpec: What, How and WhyRSpec: What, How and Why
RSpec: What, How and Why
 
Introduction to ATDD with Cucumber and RSpec
Introduction to ATDD with Cucumber and RSpecIntroduction to ATDD with Cucumber and RSpec
Introduction to ATDD with Cucumber and RSpec
 
RSpec on Rails Tutorial
RSpec on Rails TutorialRSpec on Rails Tutorial
RSpec on Rails Tutorial
 
DevDay 2016: Dave Farley - Acceptance testing for continuous delivery
DevDay 2016: Dave Farley - Acceptance testing for continuous deliveryDevDay 2016: Dave Farley - Acceptance testing for continuous delivery
DevDay 2016: Dave Farley - Acceptance testing for continuous delivery
 
software testing
 software testing software testing
software testing
 
Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013Rspec and Capybara Intro Tutorial at RailsConf 2013
Rspec and Capybara Intro Tutorial at RailsConf 2013
 
Unit testing best practices
Unit testing best practicesUnit testing best practices
Unit testing best practices
 
Unit Testing Concepts and Best Practices
Unit Testing Concepts and Best PracticesUnit Testing Concepts and Best Practices
Unit Testing Concepts and Best Practices
 
Software Testing Life Cycle
Software Testing Life CycleSoftware Testing Life Cycle
Software Testing Life Cycle
 
An Overview of User Acceptance Testing (UAT)
An Overview of User Acceptance Testing (UAT)An Overview of User Acceptance Testing (UAT)
An Overview of User Acceptance Testing (UAT)
 
React JS and why it's awesome
React JS and why it's awesomeReact JS and why it's awesome
React JS and why it's awesome
 
Software Testing Basics
Software Testing BasicsSoftware Testing Basics
Software Testing Basics
 
Agilité pour les nuls
Agilité pour les nulsAgilité pour les nuls
Agilité pour les nuls
 
Introduction to Agile software testing
Introduction to Agile software testingIntroduction to Agile software testing
Introduction to Agile software testing
 
Software Testing Fundamentals
Software Testing FundamentalsSoftware Testing Fundamentals
Software Testing Fundamentals
 
Software testing basic concepts
Software testing basic conceptsSoftware testing basic concepts
Software testing basic concepts
 
Software testing ppt
Software testing pptSoftware testing ppt
Software testing ppt
 

Semelhante a RSpec User Stories

Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Codescidept
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialYi-Ting Cheng
 
Testing C# and ASP.net using Ruby
Testing C# and ASP.net using RubyTesting C# and ASP.net using Ruby
Testing C# and ASP.net using RubyBen Hall
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsMike Subelsky
 
Ruby on Rails testing with Rspec
Ruby on Rails testing with RspecRuby on Rails testing with Rspec
Ruby on Rails testing with RspecBunlong Van
 
ruby on rails pitfalls
ruby on rails pitfallsruby on rails pitfalls
ruby on rails pitfallsRobbin Fan
 
Using Geeklog as a Web Application Framework
Using Geeklog as a Web Application FrameworkUsing Geeklog as a Web Application Framework
Using Geeklog as a Web Application FrameworkDirk Haun
 
User Login in PHP with Session & MySQL.pdf
User Login in PHP with Session & MySQL.pdfUser Login in PHP with Session & MySQL.pdf
User Login in PHP with Session & MySQL.pdfBe Problem Solver
 
Grails Simple Login
Grails Simple LoginGrails Simple Login
Grails Simple Loginmoniguna
 
Plone Interactivity
Plone InteractivityPlone Interactivity
Plone InteractivityEric Steele
 
Ruby onrails cucumber-rspec-capybara
Ruby onrails cucumber-rspec-capybaraRuby onrails cucumber-rspec-capybara
Ruby onrails cucumber-rspec-capybaraBindesh Vijayan
 
Writing Software not Code with Cucumber
Writing Software not Code with CucumberWriting Software not Code with Cucumber
Writing Software not Code with CucumberBen Mabey
 
How to implement multiple authentication guards in laravel 8
How to implement multiple authentication guards in laravel 8How to implement multiple authentication guards in laravel 8
How to implement multiple authentication guards in laravel 8Katy Slemon
 
Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::ManagerJay Shirley
 
Curso Symfony - Clase 4
Curso Symfony - Clase 4Curso Symfony - Clase 4
Curso Symfony - Clase 4Javier Eguiluz
 
Boston Computing Review - Ruby on Rails
Boston Computing Review - Ruby on RailsBoston Computing Review - Ruby on Rails
Boston Computing Review - Ruby on RailsJohn Brunswick
 
Rails antipattern-public
Rails antipattern-publicRails antipattern-public
Rails antipattern-publicChul Ju Hong
 

Semelhante a RSpec User Stories (20)

Working Effectively With Legacy Code
Working Effectively With Legacy CodeWorking Effectively With Legacy Code
Working Effectively With Legacy Code
 
OSDC 2009 Rails Turtorial
OSDC 2009 Rails TurtorialOSDC 2009 Rails Turtorial
OSDC 2009 Rails Turtorial
 
Testing C# and ASP.net using Ruby
Testing C# and ASP.net using RubyTesting C# and ASP.net using Ruby
Testing C# and ASP.net using Ruby
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
Ruby on Rails testing with Rspec
Ruby on Rails testing with RspecRuby on Rails testing with Rspec
Ruby on Rails testing with Rspec
 
Well
WellWell
Well
 
ruby on rails pitfalls
ruby on rails pitfallsruby on rails pitfalls
ruby on rails pitfalls
 
Using Geeklog as a Web Application Framework
Using Geeklog as a Web Application FrameworkUsing Geeklog as a Web Application Framework
Using Geeklog as a Web Application Framework
 
Dancing with websocket
Dancing with websocketDancing with websocket
Dancing with websocket
 
User Login in PHP with Session & MySQL.pdf
User Login in PHP with Session & MySQL.pdfUser Login in PHP with Session & MySQL.pdf
User Login in PHP with Session & MySQL.pdf
 
Grails Simple Login
Grails Simple LoginGrails Simple Login
Grails Simple Login
 
Plone Interactivity
Plone InteractivityPlone Interactivity
Plone Interactivity
 
Ruby onrails cucumber-rspec-capybara
Ruby onrails cucumber-rspec-capybaraRuby onrails cucumber-rspec-capybara
Ruby onrails cucumber-rspec-capybara
 
Writing Software not Code with Cucumber
Writing Software not Code with CucumberWriting Software not Code with Cucumber
Writing Software not Code with Cucumber
 
Jsf Ajax
Jsf AjaxJsf Ajax
Jsf Ajax
 
How to implement multiple authentication guards in laravel 8
How to implement multiple authentication guards in laravel 8How to implement multiple authentication guards in laravel 8
How to implement multiple authentication guards in laravel 8
 
Building Better Applications with Data::Manager
Building Better Applications with Data::ManagerBuilding Better Applications with Data::Manager
Building Better Applications with Data::Manager
 
Curso Symfony - Clase 4
Curso Symfony - Clase 4Curso Symfony - Clase 4
Curso Symfony - Clase 4
 
Boston Computing Review - Ruby on Rails
Boston Computing Review - Ruby on RailsBoston Computing Review - Ruby on Rails
Boston Computing Review - Ruby on Rails
 
Rails antipattern-public
Rails antipattern-publicRails antipattern-public
Rails antipattern-public
 

Último

Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksSoftradix Technologies
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?XfilesPro
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersThousandEyes
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxMalak Abu Hammad
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Patryk Bandurski
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 

Último (20)

Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Benefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other FrameworksBenefits Of Flutter Compared To Other Frameworks
Benefits Of Flutter Compared To Other Frameworks
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Pigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping ElbowsPigging Solutions Piggable Sweeping Elbows
Pigging Solutions Piggable Sweeping Elbows
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for PartnersEnhancing Worker Digital Experience: A Hands-on Workshop for Partners
Enhancing Worker Digital Experience: A Hands-on Workshop for Partners
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
Integration and Automation in Practice: CI/CD in Mule Integration and Automat...
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 

RSpec User Stories

  • 1. RSpec and User Stories A step by step tutorial By Rahoul Baruah http://www.brightbox.co.uk Released under the Creative Commons Attribution Share-Alike Licence
  • 2. What is RSpec?  Behaviour Driven Development  An evolution of Test Driven Development  Concentrates on the “behaviour” of your system  Specify the behaviour first, implement it second, refactor it third.
  • 3. What are User Stories?  Acceptance Tests for RSpec  Describe the functionality of your application in terms your customer will understand  Prove that the application does what it is supposed to.
  • 4. A Simple Authentication System  Write the feature  Write verification code for the feature  Specify the controller  Implement the controller  Specify the models  Implement the models  Verify the feature works as required  Refactor
  • 5. Write our Feature  Write our feature and save it as features/ allow-a-user-to-login.feature  Show it to the customer and have it approved  Run rake features
  • 6.  Feature: Allow a User to log in  As a user,  I want to log in,  So I can see my stuff  Scenario: Successful login  Given a user called Dave with a password of secret  And 15 items of stuff  When I log in as Dave with password secret  Then I should see the Dashboard page  And it should list my 15 items of stuff  Scenario: Unsuccessful login  Given a user called Dave with a password of secret  When I log in as Dave with password potato  Then I should see the Login page  And I should see a message saying “an incorrect username or password was supplied”
  • 7. rake features  When we run ‘rake features’ it tells us that none of the features are implemented  So we start with the first step and implement that
  • 8. Steps - proving a feature works  Create Ruby files, registration-steps.rb and session-steps.rb, in features/steps  These contain the code verifying that the feature works as expected
  • 9. registration and session steps Given /^a user called (.*) with a password of (.*)$/ do | username, password | user = User.find_by_username username user.destroy unless user.nil? visits '/registrations/new' fills_in 'User name', :with => username fills_in 'Password', :with => password fills_in 'Password Confirmation', :with => password clicks_button 'Register' end When /^I log in as (.*) with password (.*)$/ do | username, password | visits '/sessions/new' fills_in 'User name', :with => username fills_in 'Password', :with => password clicks_button 'Log in' end Then /^I should see the Dashboard page$/ do response.should redirect_to('/dashboard') end  Use Webrat to define our interactions with the application  Use RSpec to check the responses from the application
  • 10. Specify our Controller  ‘rake features’ fails  So we need to start writing some code to make it pass  But before we write any code, we need a specification  So we run… ruby script/generate rspec_controller Registrations …to build a blank controller and specification  Now to implement the RegistrationsController.  Similar work needs to be done with the SessionsController for actually logging in.
  • 11. describe RegistrationsController do describe quot;GET newquot; do it quot;should show the form to allow someone to registerquot; do on_getting :new do expect_to_create_a_blank_user end response.should be_success response.should render_template('registrations/new') end describe quot;POST createquot; do it quot;should create and log in a new userquot; do on_posting_to :create, :user => { quot;somequot; => :values } do expect_to_build_a_new_user_with quot;somequot; => :values expect_to_save_the_new_user_successfully end controller.current_user.should == @user end it quot;should redirect to the users dashboardquot; do on_posting_to :create, :user => { quot;somequot; => :values } do expect_to_build_a_new_user_with quot;somequot; => :values expect_to_save_the_new_user_successfully end
  • 12. Cont’d… it quot;should fail to create a new user if given invalid valuesquot; do on_posting_to :create, :user => { quot;somequot; => :values } do expect_to_build_a_new_user_with quot;somequot; => :values expect_to_fail_to_save_the_new_user end controller.current_user.should be_blank end it quot;should reshow the registration form if given invalid valuesquot; do on_posting_to :create, :user => { quot;somequot; => :values } do expect_to_build_a_new_user_with quot;somequot; => :values expect_to_fail_to_save_the_new_user end response.should render_template('/sessions/new') flash[:error].should == 'There were some errors when registering your details' end end end
  • 13. Specification for new registrations  Use helper methods to make the specification easier to read  Use mock objects so we are testing just the controller, not the (non-existent) models  Note how we can supply quot;somequot; => :values for the :registration parameter. As we are not using real models, the actual fields do not matter; what counts is how the controller behaves in response to certain actions.
  • 14. def expect_to_create_a_blank_user @user = mock_model User User.should_receive(:new).and_return(@user) end def expect_to_build_a_new_user_with parameters @user = mock_model User User.should_receive(:new).with(parameters).and_return(@user) end def expect_to_save_the_new_user_successfully @user.should_receive(:save!).and_return(true) end def expect_to_fail_to_save_the_new_user prepare_for_errors_on @user @user.should_receive(:save!).and_raise(ActiveRecord::RecordInvalid.new(@user)) end  The helpers build a mock user  We tell the mock to expect certain method calls and return the correct responses
  • 15. Implement the Controller  We do need to build a model… ruby script/generate rspec_model User …so that our steps will run  Remove the < ActiveRecord::Base from the definition for now (so that ActiveRecord does not complain about our lack of database tables)  But we don’t implement anything in it yet; our controller specification is using mocks so does not actually need a real object  We also need to add some routes to get things moving… map.resources :registrations map.resources :sessions map.resource :dashboard
  • 16. Implementing the Controller class RegistrationsController < ApplicationController def new @user = User.new end def create @user = User.new params[:user] @user.save! redirect_to dashboard_path rescue ActiveRecord::RecordInvalid flash[:error] = 'There were some errors when registering your details' render :template => 'registrations/new', :status => 422 end end  The implementation is pretty simple, which is exactly as it should be.
  • 17. Specifying the Model  Now we have our controller behaving as specified we need to specify the behaviour of our User model  We have already generated the RSpec files, we just need to tell it how we expect a User to behave.
  • 18. Specifying the Model  We write the specs  Update the migration to deal with the fields we need  We switch the model back so that it descends from ActiveRecord::Base  We run the migration  We implement the model
  • 19. Specifying the Model First attempt… describe User do it quot;should have a usernamequot; do @user = User.new :username => '' @user.should_not be_valid @user.should have(1).errors_on(:username) end it quot;should have a unique usernamequot; do @first_user = User.create! :username => 'arthur', :password => '12345', :password_confirmation => '12345' @second_user = User.new :username => 'arthur' @second_user.should_not be_valid @second_user.should have(1).errors.on(:username) end Cont’d…
  • 20. Cont’d… it quot;should confirm the password before savingquot; do @user = User.new :password => 'secret', :password_confirmation => 'notsecret' @user.should_not be_valid @user.should have(1).errors_on(:password) end it quot;should encrypt the password before saving to the databasequot; do PasswordEncrypter.should_receive(:encrypt).with('12345').and_return('3ncrypt3d') @user = User.new :username => 'arthur', :password => '12345', :password_confirmation => '12345' @user.save! @user.encrypted_password.should == '3ncrypt3d' end end
  • 21. Specifying the Model  There are two areas of the specification that “smell bad”  Both “it should have a unique username” and “it should encrypt the password before saving to the database” require a valid object to be saved; which in turn require knowledge of the object beyond that individual specification clause  Ideally this would not be necessary but is a problem with the ActiveRecord pattern; mixing business logic and persistence logic in a single class
  • 22.  The (imperfect) solution is to use object ‘factories’ that encapsulate knowledge of a valid model.  We are still spreading that knowledge outside of the specification but at least it is a single place to make that change (usually in spec/ spec_helper.rb)
  • 23. describe User do it quot;should have a usernamequot; do @user = a User, :username => '' @user.should_not be_valid @user.should have(1).errors_on(:username) end it quot;should have a unique usernamequot; do @first_user = a_saved User, :username => ‘arthur’ @second_user = a User, :username => 'arthur' @second_user.should_not be_valid @second_user.should have(1).errors.on(:username) end it quot;should confirm the password before savingquot; do @user = a User, :password => 'secret', :password_confirmation => 'notsecret' @user.should_not be_valid @user.should have(1).errors_on(:password) end
  • 24.  Rewritten to use “a Something” and “a_saved Something” as an object factory  Each specification clause only specifies the information it needs.  The factory ensures that the rest of the object is valid.
  • 25. Acceptance  By now we should have done enough to let the first step in our story pass its acceptance test  rake features will prove it  That should be all we need to do for that particular step - any extra development is unnecessary as it has not been requested by the customer  However, we can now safely refactor the code, to organise it better, safe in the knowledge that we can prove that it still does what is required without breakages.
  • 26. Appendix  We have a fork of RSpec for Rails that provides a set of helper methods: prepare_for_errors_on, on_getting, on_posting_to, on_putting_to and on_deleting_from  See http://github.com/rahoulb/rspec-rails/wikis/home  We are working on an object factory that makes building models (without full knowledge of their internals) a bit simpler… Object.factory.when_creating_a User, :auto_generate => :username, :auto_confirm => :password @user = a User @user = a_saved User # as above but auto-saves the user @user.should be_valid  See http://github.com/rahoulb/object-factory/wikis (although at the time of writing, November 2008, this is not quite ready)