SlideShare a Scribd company logo
RSpec on Rails
Tutorial
https://ihower.tw
2016/8
Agenda
• Rails RSpec
• Model Spec, Routing Spec, Controller Spec,
View Spec, Helper Spec
• Request Spec Feature Spec
•
• CI (Continuous Integration)
• Web
Install rspec-rails
• gem “rspec-rails”
• bundle
• rails g rspec:install
• git rm -r test
rake -T spec
• rake spec
• bundle exec rspec spec/xxx/xxx
Generators
• rails g model A
• rails g controller B
• rails g scaffold C
spec/rails_helper.rb
spec/spec_helper.rb
config.fail_fast = true
config.profile_examples = 3
config.order = :random
More Matchers
• expect(target).to eq(XXX)
• expect{ Post.find(9999) }.to
raise_error(ActiveRecord::RecordNotFound)
• expect(target).to be_xxx # target.xxx?
• expect(target).to be_a_xxx
• expect(target).to be_an_xxx
• expect(collection).to be_empty
• expect([1,2,3]).to be_include(3)
• expect({ foo: "foo" }).to have_key(:foo)
• expect(3).to be_a_kind_of(Fixnum)
• Custom matcher
rspec-rails
•
• model
• controller ( stub/mock)
• view
• helper
• routing
•
• controller ( stub/mock model )
• ( controllers )
• request
• feature ( capybara)
https://robots.thoughtbot.com/rails-test-types-and-the-testing-pyramid
Model spec syntax
let(:valid_attributes){ { :name => "Train#123"} }
expect(Event.new).to_not be_valid
expect(Event.new(valid_attributes)).to_not be_valid
Exercise 0
• Rails (ticket_office)
• rspec-rails gem
• scaffold
Exercise 1:
Train Model Spec
• Train model
• valid
Kata
• Ticket Office
• GET /trains/{train_id}
• POST /trains/{train_id}/reservations
Routing spec syntax
expect(:get => "/events").to route_to("events#index")
expect(:get => "/widgets/1/edit").not_to be_routable
But…
• ( Rails
)
• resources routing spec model
validations associations
• custom route
Controller spec syntax
get :show
post :create, :params => { :user => { :name => "a" } }
patch :update
delete :destroy
# more arguments
request.cookies[:foo] = "foo"

request.session[:bar] = “bar"
post :create, :params => { :name => "a" },
:session => { :zoo => "zoo" },
:flash => { :notice => "c"},
:format => :html
: params Rails 5.0
Matcher syntax
expect(response).to render_template(:new)
expect(response).to redirect_to(events_url)
expect(response).to have_http_status(200)
expect(assigns(:event)).to be_a_new(Event)
Isolation Mode
• controller spec render view
RSpec
• render_views
Exercise 2:
Train Controller show spec (stub
version)
• trains/show
• Train#find stub
DB
View
isolated from controller too
assign(:widget, double(“Widget”, :name => "slicer"))
render
expect(rendered).to match /slicer/
Helper spec syntax
expect(helper.your_method).to eq("Q_Q")
Exercise 3:
Train show view
• train show json view
• rails4 jbuilder
• Train
stub
Exercise 4:
• Train, Seat, SeatReservation,
Reservation models
• Train#available_seats
• controller view stub
( or Partial Stub )
What have we learned?
• stub&mock
•
stub&mocks
• ActiveRecord
Exercise 5:
• ReservationsController
• Train#reserve mock
• Train#reserve spec
• ReservationsController mock
Exercise 5`:
• Train#reserve spec
• ReservationsController
( mock)
Exercise 6:
• GET /trains/{id}
• POST /trains/{id}/reservations
• POST /trains/{id}/reservations
Factory v.s. Fixtures
• rails fixtures YAML DB
• model
validation
• factory ActiveRecord
• factory_girl gem fabrication gem
•
• ActiveReocrd
• factory_girl trait
unit test
• model object DB build
create build_stubbed
factory_girl
FactoryGirl.define do
factory :user do
firstname "John"
lastname "Doe"
sequence(:email) { |n| "test#{n}@example.com"}
association :profile, :factory => :profile
end
factory :profile do
bio "ooxx"
end
end
factory_girl
before do
@user = build(:user) # DB
@event = create(:event) # DB
end
it "should post user data"
post :create, :params => { :user => attributes_for(:user) }
# ...
end
• https://github.com/thoughtbot/factory_girl/
blob/master/GETTING_STARTED.md
• https://thoughtbot.com/upcase/videos/
factory-girl
Tip: support
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
# support/factory_helpers.rb
module FactoryHelpers
# ...
end
Rspec.configure do |config|
config.include FactoryHelpers
end
Exercise 7: Extract to
factory method
• Train Extract support/
factory.rb
Tip: stub
before(:each) {
allow(controller).to receive(:current_user) { ... }
}
Tip: focus
• :focus => true describe
it
• rspec --tag focus
•
config.filter_run :focus => true
config.run_all_when_everything_filtered = true
Request
• full-stack
• stub
• Web APIs JSON, XML
• Request
controllers
• sessions ( )
• Matchers controller spec
Request spec syntax
describe "GET /events" do
it "works! (now write some real specs)" do
get “/events”
expect(response).to have_http_status(200)
end
end
Example: controller
it "creates a Widget and redirects to the Widget's page" do
get "/widgets/new"
expect(response).to render_template(:new)
post "/widgets", :widget => {:name => "My Widget"}
expect(response).to redirect_to(assigns(:widget))
follow_redirect!
expect(response).to render_template(:show)
expect(response.body).to include("Widget was successfully created.")
end
Exercise 8:
• 1. 2. 3.
Feature spec
• capybara gem request spec
• http://rubydoc.info/github/jnicklas/capybara/
master
• Capybara HTML
Capybara example
feature "signing up" do
background do
User.create(:email => 'user@example.com', :password => 'caplin')
end
scenario "signing in with correct credentials" do
visit "/" # or root_path
click_link 'Log In'
within("#session") do
fill_in 'Login', :with => 'user@example.com'
fill_in 'Password', :with => 'caplin'
choose('some_select_option_yes')
check('some_checkbox')
end
click_button 'Sign in'
expect(User.count).to eq(1) # you can test model
expect(page).to have_content 'Login successfuuly' # and/or test page
end
end
find css selector xpath
Debugging
• save_and_open_page
• capybara-screenshot gem
•
JavaScript Driver
• Capybara javascript
• javascript_driver
Ruby README
• https://github.com/teampoltergeist/poltergeist
PhantomJS
• https://github.com/thoughtbot/capybara-webkit
QtWebKit
• https://rubygems.org/gems/selenium-webdriver
Firefox
• test js: true
JavaScript Driver
• Browser tools Rails Ruby
thread
• DB transaction database cleaner
• https://github.com/DatabaseCleaner/database_cleaner
• https://github.com/amatsuda/database_rewinder
• javascript (
Ajax)
• Capybara 5
• Capybara.default_wait_time
• using_wait_time(2) { …. }
https://robots.thoughtbot.com/write-reliable-asynchronous-integration-tests-with-capybara
• Extract behavior to helper methods
• Page Object
https://robots.thoughtbot.com/acceptance-tests-at-a-single-level-of-
abstraction
Page Object
http://www.infoq.com/cn/articles/martin-fowler-basic-rule-of-thumbon-for-Web-testing
Page Object example
https://teamgaslight.com/blog/6-ways-to-remove-pain-from-feature-testing-in-ruby-on-rails
https://thoughtbot.com/upcase/videos/page-objects
https://robots.thoughtbot.com/better-acceptance-tests-with-page-objects
https://medium.com/neo-innovation-ideas/clean-up-after-your-capybara-1a08b47a499b#.oyl7zi44d
https://www.sitepoint.com/testing-page-objects-siteprism/
(1)
• Debugging ?
• puts
• https://tenderlovemaking.com/2016/02/05/i-am-
a-puts-debuggerer.html
• byebug
• --only-failures option
• https://relishapp.com/rspec/rspec-core/docs/
command-line/only-failures
(2)
• Time.now ?
• http://api.rubyonrails.org/classes/
ActiveSupport/Testing/TimeHelpers.html
travel_to
• config.include
ActiveSupport::Testing::TimeHelpers
• Timecop gem
(3)
• email ?
• mail = ActionMailer::Base.deliveries.last
• config.before(:each)
{ ActionMailer::Base.deliveries.clear }
• https://github.com/email-spec/email-
spec/
(4)
• ?
• spec/fixtures/
• File.new(Rails.root + ‘spec/fixtures/
foobar.png') paperclip
Photo.create(:description => "Test", :attachment
=> File.new(Rails.root + ‘spec/fixtures/ac_logo.png'))
• feature spec capybara attach_file
http://www.rubydoc.info/github/jnicklas/capybara/
master/Capybara%2FNode%2FActions%3Aattach_file
(5)
• devise https://github.com/plataformatec/
devise Test helpers
config.include Devise::Test::ControllerHelpers, type: :controller
config.include Devise::Test::ControllerHelpers, type: :view
config.include Devise::Test::IntegrationHelpers, type: :feature
(6)
• sidekiq ?
• http://api.rubyonrails.org/classes/
ActiveJob/TestHelper.html#method-i-
perform_enqueued_jobs
• config.include ActiveJob::TestHelper
• enqueue job
perform_enqueued_jobs
{ … }
(7)
• after_commit ?
• unit test transaction after_commit
• https://github.com/grosser/test_after_commit
• database_cleanner truncation transaction
• trigger
• http://mytrile.github.io/blog/2013/03/28/testing-after-
commit-in-rspec/
• Rails 5.0 workaround
(8)
• rake ?
• model class
method
• model spec
(9)
• legacy ?
• happy path feature spec C/P
• Unit test
•
• Unit Test
(10)
• ?
• Test double (?)
• CPU
• https://github.com/grosser/parallel_tests
• CI concurrent build
Tools
• shoulda rails matcher
• database_cleaner DB
• vcr HTTP response 3-party
service
• simplecov
• cucumber
• CI (continuous integration (CI)
BDD
http://www.tenlong.com.tw/items/9862019484?
item_id=997422
simplecov
?
Coverage
!
CI
• 3-party service
• https://www.codeship.io
• https://circleci.com/
• https://travis-ci.org/
• build your own
• Jenkins
?
Spec
• Rspec spec
•
• Custom Matcher
Test Pyramid
http://watirmelon.com/2012/01/31/introducing-the-software-testing-ice-cream-cone/
http://martinfowler.com/bliki/TestPyramid.html
developer 

QA XD

salesforce ?
RSpec on Rails Tutorial
https://www.quora.com/What-is-the-best-way-to-test-the-web-application
What is the best way to test the web application?
Why?
• low-level
debug
• high-level
debug
• view
• developer
QA
• bug failures
trace
•
•
( Mocks )
https://thoughtbot.com/upcase/videos/testing-antipatterns
Isolation
• it
Expectation
•
• one failure one problem 

trace
describe "#amount" do
it "should discount" do
user.vip = true
order.amount.should == 900
user.vip = false
order.amount.should == 1000
end
end
context
describe "#amount" do
context "when user is vip" do
it "should discount ten percent" do
user.vip = true
order.amount.should == 900
end
end
context "when user is not vip" do
it "should discount five percent" do
user.vip = false
order.amount.should == 1000
end
end
end
• Private methods
•
Private methods
class Order
def amount
if @user.vip?
self.caculate_amount_for_vip
else
self.caculate_amount_for_non_vip
end
end
private
def caculate_amount_for_vip
# ...
end
def caculate_amount_for_non_vip
# ...
end
end
it "should discount for vip" do
@order.send(:caculate_amount_for_vip).should == 900
end
it "should discount for non vip" do
@order.send(:caculate_amount_for_vip).should == 1000
end
Private methods
• public
private/protect methods
• private
• public
• Public methods
Private/Protected
describe User do
describe '.search' do
it 'searches Google for the given query' do
HTTParty.should_receive(:get).with('http://www.google.com',
:query => { :q => 'foo' } ).and_return([])
User.search query
end
end
end
HTTP
describe User do
describe '.search' do
it 'searches for the given query' do
User.searcher = Searcher
Searcher.should_receive(:search).with('foo').and_return([])
User.search query
end
end
end
class User < ActiveRecord::Base
class_attribute :searcher
def self.search(query)
searcher.search query
end
end
class Searcher
def self.search(keyword, options={})
HTTParty.get(keyword, options)
end
end
?
RSpec on Rails Tutorial
TATFT
test all the f**king time
RSpec on Rails Tutorial
bug
bug
bug
DHH Way
• 100% test coverage
• Code-to-test 1:2 1:3
• 1/3
• Active Record associations, validations, or scopes.
• ( Unit Test )
• Cucumber
• Specification by Example
• TDD (DHH 20% TDD)
• Model DB Fixtures
• Controller
• Views system/browser testing
https://signalvnoise.com/posts/3159-testing-like-the-tsa
http://david.heinemeierhansson.com/2014/test-induced-design-damage.html
?
coverage?
code review
pair programming
EPIC FAIL
RSpec on Rails Tutorial
Unit Test
Reference:
• http://guides.rubyonrails.org/testing.html
• https://github.com/eliotsykes/rspec-rails-examples#api-request-specs-docs--
helpers
• The RSpec Book
• The Rails 3 Way
• Foundation Rails 2
• xUnit Test Patterns
• everyday Rails Testing with RSpec
• http://betterspecs.org/
• http://pure-rspec-rubynation.heroku.com/
• http://jamesmead.org/talks/2007-07-09-introduction-to-mock-objects-in-ruby-at-lrug/
• http://martinfowler.com/articles/mocksArentStubs.html
• http://blog.rubybestpractices.com/posts/gregory/034-issue-5-testing-antipatterns.html
• http://blog.carbonfive.com/2011/02/11/better-mocking-in-ruby/
Thanks.

More Related Content

PDF
RSpec & TDD Tutorial
PDF
RSpec 讓你愛上寫測試
PDF
Threads 08: Executores e Futures
PPTX
Comparative Analysis Of GoLang Testing Frameworks
PDF
PDF
Functional Domain Modeling - The ZIO 2 Way
PPT
Google mock for dummies
PDF
Spark schema for free with David Szakallas
RSpec & TDD Tutorial
RSpec 讓你愛上寫測試
Threads 08: Executores e Futures
Comparative Analysis Of GoLang Testing Frameworks
Functional Domain Modeling - The ZIO 2 Way
Google mock for dummies
Spark schema for free with David Szakallas

What's hot (15)

PPTX
Mov is turing-complete
PDF
Functional Error Handling with Cats
PPT
presentacion_Alejandro_Penabad.ppt
PPTX
Back to [Jaspersoft] basics: visualize.js 101
PDF
GraphQL Fundamentals
PPT
Logstash
PDF
Ruby Rails 老司機帶飛
PDF
Functor, Apply, Applicative And Monad
PDF
Python Functions (PyAtl Beginners Night)
PDF
[pgday.Seoul 2022] 서비스개편시 PostgreSQL 도입기 - 진소린 & 김태정
PDF
Introduction to Elixir
PDF
Wroclaw GraphQL - GraphQL in Java
PDF
TestNG Annotations in Selenium | Edureka
PDF
Sagas Middleware Architecture
PDF
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...
Mov is turing-complete
Functional Error Handling with Cats
presentacion_Alejandro_Penabad.ppt
Back to [Jaspersoft] basics: visualize.js 101
GraphQL Fundamentals
Logstash
Ruby Rails 老司機帶飛
Functor, Apply, Applicative And Monad
Python Functions (PyAtl Beginners Night)
[pgday.Seoul 2022] 서비스개편시 PostgreSQL 도입기 - 진소린 & 김태정
Introduction to Elixir
Wroclaw GraphQL - GraphQL in Java
TestNG Annotations in Selenium | Edureka
Sagas Middleware Architecture
N-Queens Combinatorial Problem - Polyglot FP for Fun and Profit – Haskell and...
Ad

Viewers also liked (20)

PDF
淺談 Startup 公司的軟體開發流程 v2
PDF
ALPHAhackathon: How to collaborate
PDF
RubyConf Taiwan 2012 Opening & Closing
PDF
RSpec 2 Best practices
PDF
Testing Ruby with Rspec (a beginner's guide)
PDF
Git 版本控制系統 -- 從微觀到宏觀
PDF
那些 Functional Programming 教我的事
PDF
[DSC 2016] 系列活動:李宏毅 / 一天搞懂深度學習
PDF
Practical Scrum with Kent Beck (SD Times Webinar)
PDF
Testing with Rspec 3
PDF
RSpec User Stories
PPTX
RSpec and Rails
PDF
Introduction to test_driven_development
PDF
Monitoring web application behaviour with cucumber-nagios
PPTX
Rspec 101
PDF
Behavior Driven Development - How To Start with Behat
PPTX
RSpec: What, How and Why
PDF
RubyConf Taiwan 2011 Opening & Closing
PDF
Ruby 程式語言綜覽簡介
PDF
Yet another introduction to Git - from the bottom up
淺談 Startup 公司的軟體開發流程 v2
ALPHAhackathon: How to collaborate
RubyConf Taiwan 2012 Opening & Closing
RSpec 2 Best practices
Testing Ruby with Rspec (a beginner's guide)
Git 版本控制系統 -- 從微觀到宏觀
那些 Functional Programming 教我的事
[DSC 2016] 系列活動:李宏毅 / 一天搞懂深度學習
Practical Scrum with Kent Beck (SD Times Webinar)
Testing with Rspec 3
RSpec User Stories
RSpec and Rails
Introduction to test_driven_development
Monitoring web application behaviour with cucumber-nagios
Rspec 101
Behavior Driven Development - How To Start with Behat
RSpec: What, How and Why
RubyConf Taiwan 2011 Opening & Closing
Ruby 程式語言綜覽簡介
Yet another introduction to Git - from the bottom up
Ad

Similar to RSpec on Rails Tutorial (20)

PPT
TDD, BDD, RSpec
PDF
Tootle returning to rails
PPTX
Rspec presentation
PDF
2011-02-03 LA RubyConf Rails3 TDD Workshop
PDF
Basic RSpec 2
PPT
Ruby on Rails testing with Rspec
PPTX
Behavioural Testing Ruby/Rails Apps @ Scale - Rspec & Cucumber
PDF
Effectively Testing Services - Burlington Ruby Conf
KEY
How To Test Everything
PDF
Rethinking Testing
KEY
Testing gone-right
KEY
Speedy TDD with Rails
PPTX
Autotesting rails app
PDF
Capybara with Rspec
PPT
[Srijan Wednesday Webinar] Rails 5: What's in It for Me?
PDF
Automated Testing with Ruby
PDF
Sinatra and JSONQuery Web Service
PPTX
Rails automatic test driven development
PDF
Testing Ember Apps
TDD, BDD, RSpec
Tootle returning to rails
Rspec presentation
2011-02-03 LA RubyConf Rails3 TDD Workshop
Basic RSpec 2
Ruby on Rails testing with Rspec
Behavioural Testing Ruby/Rails Apps @ Scale - Rspec & Cucumber
Effectively Testing Services - Burlington Ruby Conf
How To Test Everything
Rethinking Testing
Testing gone-right
Speedy TDD with Rails
Autotesting rails app
Capybara with Rspec
[Srijan Wednesday Webinar] Rails 5: What's in It for Me?
Automated Testing with Ruby
Sinatra and JSONQuery Web Service
Rails automatic test driven development
Testing Ember Apps

More from Wen-Tien Chang (19)

PDF
評估驅動開發 Eval-Driven Development (EDD): 生成式 AI 軟體不確定性的解決方法
PDF
⼤語⾔模型 LLM 應⽤開發入⾨
PDF
A brief introduction to Machine Learning
PDF
Exception Handling: Designing Robust Software in Ruby (with presentation note)
PDF
Exception Handling: Designing Robust Software in Ruby
PDF
從 Classes 到 Objects: 那些 OOP 教我的事
PDF
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
PDF
A brief introduction to SPDY - 邁向 HTTP/2.0
PDF
從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup
PDF
Git Tutorial 教學
PDF
BDD style Unit Testing
PDF
Git and Github
PDF
Service-Oriented Design and Implement with Rails3
PDF
Rails3 changesets
PDF
遇見 Ruby on Rails
PDF
Designing Ruby APIs
PDF
Rails Security
PDF
Rails Performance
PDF
Distributed Ruby and Rails
評估驅動開發 Eval-Driven Development (EDD): 生成式 AI 軟體不確定性的解決方法
⼤語⾔模型 LLM 應⽤開發入⾨
A brief introduction to Machine Learning
Exception Handling: Designing Robust Software in Ruby (with presentation note)
Exception Handling: Designing Robust Software in Ruby
從 Classes 到 Objects: 那些 OOP 教我的事
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
A brief introduction to SPDY - 邁向 HTTP/2.0
從 Scrum 到 Kanban: 為什麼 Scrum 不適合 Lean Startup
Git Tutorial 教學
BDD style Unit Testing
Git and Github
Service-Oriented Design and Implement with Rails3
Rails3 changesets
遇見 Ruby on Rails
Designing Ruby APIs
Rails Security
Rails Performance
Distributed Ruby and Rails

Recently uploaded (20)

PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Modernizing your data center with Dell and AMD
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Advanced methodologies resolving dimensionality complications for autism neur...
PPTX
Cloud computing and distributed systems.
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Reach Out and Touch Someone: Haptics and Empathic Computing
DOCX
The AUB Centre for AI in Media Proposal.docx
PDF
KodekX | Application Modernization Development
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPTX
MYSQL Presentation for SQL database connectivity
PDF
Building Integrated photovoltaic BIPV_UPV.pdf
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
PPTX
Understanding_Digital_Forensics_Presentation.pptx
PDF
Empathic Computing: Creating Shared Understanding
PDF
Machine learning based COVID-19 study performance prediction
PDF
Encapsulation_ Review paper, used for researhc scholars
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
20250228 LYD VKU AI Blended-Learning.pptx
Modernizing your data center with Dell and AMD
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Advanced methodologies resolving dimensionality complications for autism neur...
Cloud computing and distributed systems.
Network Security Unit 5.pdf for BCA BBA.
Reach Out and Touch Someone: Haptics and Empathic Computing
The AUB Centre for AI in Media Proposal.docx
KodekX | Application Modernization Development
Mobile App Security Testing_ A Comprehensive Guide.pdf
MYSQL Presentation for SQL database connectivity
Building Integrated photovoltaic BIPV_UPV.pdf
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Dropbox Q2 2025 Financial Results & Investor Presentation
Build a system with the filesystem maintained by OSTree @ COSCUP 2025
Understanding_Digital_Forensics_Presentation.pptx
Empathic Computing: Creating Shared Understanding
Machine learning based COVID-19 study performance prediction
Encapsulation_ Review paper, used for researhc scholars

RSpec on Rails Tutorial