SlideShare ist ein Scribd-Unternehmen logo
1 von 47
Downloaden Sie, um offline zu lesen
Controller Specs
Xander Miller
@pareidoliax
What is Controller
Testing?
Why Controller Test?
Tools
RSpec
FactoryGirl
General RSpec Tips
RSpec Tips
• Configuration: Color, Verbose
• Alias bundle exec
• description text should build the user story
• add comments to your end statements
Configuration
~/.rspec
--require spec_helper
--color
--format documentation
bundle install --no-rdoc
Alias Bundle exec
alias brspec="bundle exec rspec"
alias be="bundle exec"
Description Text builds a User
Story
TagsController
when authorized User (admin)
the DELETE #destroy action
behaves like a 302 redirect request action
redirects to :back (root_path)
RSpec Gotchas
RSPec Gotchas
• Scoping is weird
it_behaves_like "a 302 redirect request action", ":back (root_path)" do
let!(:put_update) {put :update, id: @user.id, user: @user_attributes}
let(:redirect_path) {root_path}
end
• Relish Docs
How to RSpec
How to RSpec
OO BB Object Oriented Black Box
• Given (Context)
• When (Event)
• Then (Expected Result)
Applying it to
Controllers
Given
• Session
• Domain Object Layer status
• Params
When
• HTTP Request with Params
Then
• Flash Messages
• Assigns Instance Variables (decorators)
• Domain Object Layer Changes
Keeping it DRY
• before Hooks (given)
• let (when)
• shared examples
before :example
before :example do
@admin = create(:admin)
session[:user_id] = @admin.id
end
let :example
let!(:post_create) {post :create, user: @user_attributes}
let(:redirect_path) {root_path}
shared examples: 3 types of
RESTful responses
• successful GET action
• redirect 302 action
• unauthorized action 302 redirect
successful GET action
RSpec.shared_examples_for 'an unauthorized action' do
it "responds redirect with an HTTP 302 status code" do
expect(response).to be_redirect
expect(response).to have_http_status(:found)
end
it "provides a flash alert message" do
expect(flash[:warning]).to_not be_nil
end
it "redirects to login_path" do
expect(response).to redirect_to login_path
end
end
redirect 302 action
RSpec.shared_examples_for "a 302 redirect request action" do |path_name|
it "responds with a redirect HTTP 302 status code" do
expect(response).to be_redirect
expect(response).to have_http_status(:found)
end
it "redirects to #{path_name}" do
expect(response).to redirect_to redirect_path
end
end
unauthorized action 302 redirect
RSpec.shared_examples_for 'an unauthorized action' do
it "responds redirect with an HTTP 302 status code" do
expect(response).to be_redirect
expect(response).to have_http_status(:found)
end
it "provides a flash alert message" do
expect(flash[:warning]).to_not be_nil
end
it "redirects to login_path" do
expect(response).to redirect_to login_path
end
end
Overall Structure of a
Controller Spec
require 'support/controller_helper'
describe UsersController do
context 'when unauthorized (no User)' do
describe "the GET #new action" do
end # describe "the GET #new action" do
describe "the POST #create action" do
context "is provided valid User params and" do
end # context "is provided valid User params and" do
context "is provided invalid User params and" do
end # context "is provided invalid User params and" do
end # describe "the POST #create action" do
describe "the GET #show action" do
end # describe "the GET #show action" do
end # context 'when unauthorized (no User signed in)' do
context 'when authorized (Admin User)' do
describe "the GET #index action" do
end #describe "the GET #index action" do
describe "the PUT #update action" do
context "is provided valid user params and" do
end # "is provided valid user params and" do
context "is provided invalid user params and" do
end # "is provided invalid user params and" do
end # "the PUT #update action" do
end # context 'when authorized (Admin User)' do
end
Example Specs
Unauthorized Action
describe "the GET #show action" do
before :example do
@user = create(:user)
end
it_behaves_like 'an unauthorized action' do
let!(:get_show) {get :show, {id: @user.id}}
end
end # describe "the GET #show action" do
Examples by RESTful
Action
GET #show
describe "the GET #show action" do
before :example do
@user = create(:user)
end
it_behaves_like "a successful GET action", :show do
let!(:get_show) {get :show, {id: @user.id}}
end
let(:get_show) {get :show, {id: @user.id}}
it "assigns a valid UserDecorator of to @user" do
get_show
@decorated_user = UserDecorator.new @user
expect(assigns(:user)).to be_kind_of(UserDecorator)
expect(assigns(:user)).to eq(@decorated_user)
end
end # describe "the GET #show action" do
GET #index
describe "the GET #index action" do
it_behaves_like "a successful GET action", :index do
let!(:get_index) {get :index}
end
let(:get_index) {get :index}
GET #index con'd
it "loads the users in the current users, current region" do
region = create(:region)
user1, user2 = create(:user), create(:user)
[@admin, user1, user2].each do |u|
u.add_to_region! region
u.current_region = region
u.save
end
get_index
expect(assigns(:users)).to
match_array([@admin.reload, user1.reload, user2.reload])
end
end #describe "the GET #index action" do
GET #new
describe "the GET #new action" do
it_behaves_like "a successful GET action", :new do
let!(:get_new) {get :new}
end
let!(:get_new) {get :new}
it "assigns a unsaved User to @user" do
expect(assigns(:user)).to be_kind_of(User)
expect(assigns(:user)).to respond_to(:id).with(nil)
end
end # describe "the GET #new action" do
POST #create
describe "the POST #create action" do
before :example do
@user_attributes = attributes_for(:user)
request.env["HTTP_REFERER"] = root_path
end
let(:post_create) {post :create, user: @user_attributes}
POST #create con't
context "is provided valid User params and" do
it_behaves_like "a 302 redirect request action", ':back (to root_path)' do
let!(:post_create) {post :create, user: @user_attributes}
let(:redirect_path) {root_path}
end
it "creates a user" do
expect { post_create }.to change(User, :count).by(1)
end
it "provides a flash success message" do
post_create
expect(flash[:success]).to_not be_nil
end
end # context "is provided valid User params and" do
POST #create con't con't
context "is provided invalid User params and" do
before :example do
@user_attributes = attributes_for(:user)
User.create @user_attributes
end
it_behaves_like "a 302 redirect request action", 'new_user_path' do
let!(:post_create) {post :create, user: @user_attributes}
let(:redirect_path) {new_user_path}
end
it "fails to create a new user" do
expect { post :create, user: @user_attributes }.not_to change(User, :count)
end
it "provides a flash danger message" do
post_create
expect(flash[:danger]).to_not be_nil
end
end # context "is provided invalid User params and" do
end # describe "the POST #create action" do
GET #edit
describe "the GET #edit action" do
before :example do
@user = create(:user)
end
it_behaves_like "a successful GET action", :edit do
let!(:get_edit) {get :edit, {id: @user.id}}
end
let(:get_edit) {get :edit, {id: @user.id}}
it "loads all of the roles from User class into @roles" do
roler = class_double("User")
allow(roler).to receive(:roles).and_return([:worker, :manager, :organizer, :moderator, :admin])
get_edit
expect(assigns(:roles)).to match_array([:worker, :manager, :organizer, :moderator, :admin])
end
GET #edit c
on't
it "loads all of the regions from Region class into @regions" do
region1, region2 = create(:region), create(:region)
get_edit
expect(assigns(:regions)).to match_array([region1, region2])
end
it "assigns valid UserDecorator to @user" do
get_edit
@decorated_user = UserDecorator.new @user
expect(assigns(:user)).to be_kind_of(UserDecorator)
expect(assigns(:user)).to eq(@decorated_user)
end
end # describe "the GET #edit action" do
PATCH #update
describe "the PUT #update action" do
let(:put_update) {put :update, id: @user.id, user: @user_attributes}
context "is provided valid user params and" do
before :example do
@user_attributes = attributes_for(:user).merge({email: "vengeful_spirit@example.com"})
@user = User.create @user_attributes.merge({email: "sneaky_jugger@example.com"})
end
it_behaves_like "a 302 redirect request action", "@user" do
let!(:put_update) {put :update, id: @user.id, user: @user_attributes}
let(:redirect_path) {@user}
end
PATCH #update con't
it "changes user email attribute" do
expect(@user.reload.email).to eq("sneaky_jugger@example.com")
put_update
expect(@user.reload.email).to eq("vengeful_spirit@example.com")
end
it "provides a flash success message" do
put_update
expect(flash[:success]).to_not be_nil
end
end # "is provided valid user params and" do
PATCH #update con't con't
context "is provided invalid user params and" do
before :example do
@user_attributes = attributes_for(:user).merge({email: "vengeful_spirit.example.com"})
@user = User.create @user_attributes.merge({email: "sneaky_jugger@example.com"})
request.env["HTTP_REFERER"] = root_path
end
it_behaves_like "a 302 redirect request action", ":back (root_path)" do
let!(:put_update) {put :update, id: @user.id, user: @user_attributes}
let(:redirect_path) {root_path}
end
PATCH #update con't con't con't
it "fails to change user email attribute" do
expect(@user.reload.email).to eq("sneaky_jugger@example.com")
put_update
expect(@user.reload.email).to eq("sneaky_jugger@example.com")
end
it "provides a flash danger message" do
put_update
expect(flash[:danger]).to_not be_nil
end
end # "is provided invalid user params and" do
end # "the PUT #update action" do
DELETE #destroy
describe "the DELETE #destroy action" do
before :example do
@tag = create(:tag)
request.env["HTTP_REFERER"] = tags_path
end
let(:delete_destroy) {delete :destroy, id: @tag.id }
it "destroys @tag" do
expect {delete_destroy}.to change(Tag, :count).by(-1)
end
it_behaves_like "a 302 redirect request action", "tags_path (:back)" do
let!(:delete_destroy) {delete :destroy, id: @tag.id }
let(:redirect_path) {tags_path}
end
end
Resources
• Everyday Rails: How I learned to test my Rails applications
• Relish: RSpec Docs
• Code School: Testing with RSpec
• Code Examples
That's all Folks!
@pareidoliax
xandermiller.ca
xander.miller@gmail.com

Weitere ähnliche Inhalte

Was ist angesagt?

Quick start with React | DreamLab Academy #2
Quick start with React | DreamLab Academy #2Quick start with React | DreamLab Academy #2
Quick start with React | DreamLab Academy #2DreamLab
 
Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3 Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3 DreamLab
 
Introduction to ReactJS and Redux
Introduction to ReactJS and ReduxIntroduction to ReactJS and Redux
Introduction to ReactJS and ReduxBoris Dinkevich
 
Evan Schultz - Angular Summit - 2016
Evan Schultz - Angular Summit - 2016Evan Schultz - Angular Summit - 2016
Evan Schultz - Angular Summit - 2016Evan Schultz
 
Implementing Server Side Data Synchronization for Mobile Apps
Implementing Server Side Data Synchronization for Mobile AppsImplementing Server Side Data Synchronization for Mobile Apps
Implementing Server Side Data Synchronization for Mobile AppsMichele Orselli
 
Reactive.architecture.with.Angular
Reactive.architecture.with.AngularReactive.architecture.with.Angular
Reactive.architecture.with.AngularEvan Schultz
 
«Работа с базами данных с использованием Sequel»
«Работа с базами данных с использованием Sequel»«Работа с базами данных с использованием Sequel»
«Работа с базами данных с использованием Sequel»Olga Lavrentieva
 
Server side data sync for mobile apps with silex
Server side data sync for mobile apps with silexServer side data sync for mobile apps with silex
Server side data sync for mobile apps with silexMichele Orselli
 
Timothy N. Tsvetkov, Rails 3.1
Timothy N. Tsvetkov, Rails 3.1Timothy N. Tsvetkov, Rails 3.1
Timothy N. Tsvetkov, Rails 3.1Evil Martians
 
Creating a WYSIWYG Editor with React
Creating a WYSIWYG Editor with ReactCreating a WYSIWYG Editor with React
Creating a WYSIWYG Editor with Reactpeychevi
 
Design for succcess with react and storybook.js
Design for succcess with react and storybook.jsDesign for succcess with react and storybook.js
Design for succcess with react and storybook.jsChris Saylor
 
Interoperable Component Patterns
Interoperable Component PatternsInteroperable Component Patterns
Interoperable Component PatternsMatthew Beale
 
React.js workshop by tech47.in
React.js workshop by tech47.inReact.js workshop by tech47.in
React.js workshop by tech47.inJaikant Kumaran
 
Violet Peña - Storybook: A React Tool For Your Whole Team
Violet Peña - Storybook: A React Tool For Your Whole TeamViolet Peña - Storybook: A React Tool For Your Whole Team
Violet Peña - Storybook: A React Tool For Your Whole TeamAnton Caceres
 
Implementing data sync apis for mibile apps @cloudconf
Implementing data sync apis for mibile apps @cloudconfImplementing data sync apis for mibile apps @cloudconf
Implementing data sync apis for mibile apps @cloudconfMichele Orselli
 
Peggy angular 2 in meteor
Peggy   angular 2 in meteorPeggy   angular 2 in meteor
Peggy angular 2 in meteorLearningTech
 
PHPUnit with Mocking and Crawling
PHPUnit with Mocking and CrawlingPHPUnit with Mocking and Crawling
PHPUnit with Mocking and CrawlingTrung x
 
Reliable Javascript
Reliable Javascript Reliable Javascript
Reliable Javascript Glenn Stovall
 
Modern Web Developement
Modern Web DevelopementModern Web Developement
Modern Web Developementpeychevi
 

Was ist angesagt? (20)

Quick start with React | DreamLab Academy #2
Quick start with React | DreamLab Academy #2Quick start with React | DreamLab Academy #2
Quick start with React | DreamLab Academy #2
 
React lecture
React lectureReact lecture
React lecture
 
Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3 Intro to Redux | DreamLab Academy #3
Intro to Redux | DreamLab Academy #3
 
Introduction to ReactJS and Redux
Introduction to ReactJS and ReduxIntroduction to ReactJS and Redux
Introduction to ReactJS and Redux
 
Evan Schultz - Angular Summit - 2016
Evan Schultz - Angular Summit - 2016Evan Schultz - Angular Summit - 2016
Evan Schultz - Angular Summit - 2016
 
Implementing Server Side Data Synchronization for Mobile Apps
Implementing Server Side Data Synchronization for Mobile AppsImplementing Server Side Data Synchronization for Mobile Apps
Implementing Server Side Data Synchronization for Mobile Apps
 
Reactive.architecture.with.Angular
Reactive.architecture.with.AngularReactive.architecture.with.Angular
Reactive.architecture.with.Angular
 
«Работа с базами данных с использованием Sequel»
«Работа с базами данных с использованием Sequel»«Работа с базами данных с использованием Sequel»
«Работа с базами данных с использованием Sequel»
 
Server side data sync for mobile apps with silex
Server side data sync for mobile apps with silexServer side data sync for mobile apps with silex
Server side data sync for mobile apps with silex
 
Timothy N. Tsvetkov, Rails 3.1
Timothy N. Tsvetkov, Rails 3.1Timothy N. Tsvetkov, Rails 3.1
Timothy N. Tsvetkov, Rails 3.1
 
Creating a WYSIWYG Editor with React
Creating a WYSIWYG Editor with ReactCreating a WYSIWYG Editor with React
Creating a WYSIWYG Editor with React
 
Design for succcess with react and storybook.js
Design for succcess with react and storybook.jsDesign for succcess with react and storybook.js
Design for succcess with react and storybook.js
 
Interoperable Component Patterns
Interoperable Component PatternsInteroperable Component Patterns
Interoperable Component Patterns
 
React.js workshop by tech47.in
React.js workshop by tech47.inReact.js workshop by tech47.in
React.js workshop by tech47.in
 
Violet Peña - Storybook: A React Tool For Your Whole Team
Violet Peña - Storybook: A React Tool For Your Whole TeamViolet Peña - Storybook: A React Tool For Your Whole Team
Violet Peña - Storybook: A React Tool For Your Whole Team
 
Implementing data sync apis for mibile apps @cloudconf
Implementing data sync apis for mibile apps @cloudconfImplementing data sync apis for mibile apps @cloudconf
Implementing data sync apis for mibile apps @cloudconf
 
Peggy angular 2 in meteor
Peggy   angular 2 in meteorPeggy   angular 2 in meteor
Peggy angular 2 in meteor
 
PHPUnit with Mocking and Crawling
PHPUnit with Mocking and CrawlingPHPUnit with Mocking and Crawling
PHPUnit with Mocking and Crawling
 
Reliable Javascript
Reliable Javascript Reliable Javascript
Reliable Javascript
 
Modern Web Developement
Modern Web DevelopementModern Web Developement
Modern Web Developement
 

Andere mochten auch (15)

RSpec and Rails
RSpec and RailsRSpec and Rails
RSpec and Rails
 
Pt client-and-heaelth-history-for-big-loser-community
Pt client-and-heaelth-history-for-big-loser-communityPt client-and-heaelth-history-for-big-loser-community
Pt client-and-heaelth-history-for-big-loser-community
 
Jhonathan galindo
Jhonathan galindoJhonathan galindo
Jhonathan galindo
 
Nectar
NectarNectar
Nectar
 
Bala Portfolio
Bala PortfolioBala Portfolio
Bala Portfolio
 
講演会スライド
講演会スライド講演会スライド
講演会スライド
 
Nectar
NectarNectar
Nectar
 
Lifestyle balance-pie -e
Lifestyle balance-pie -eLifestyle balance-pie -e
Lifestyle balance-pie -e
 
Chemistry project
Chemistry projectChemistry project
Chemistry project
 
Magnetic Moment Issue 98, Quarter 1, 2015:
Magnetic Moment Issue 98, Quarter 1, 2015:Magnetic Moment Issue 98, Quarter 1, 2015:
Magnetic Moment Issue 98, Quarter 1, 2015:
 
Kaedah fonetik
Kaedah fonetikKaedah fonetik
Kaedah fonetik
 
PRESENTATION ON MOUNTAIN DEW sheni
PRESENTATION ON MOUNTAIN DEW sheniPRESENTATION ON MOUNTAIN DEW sheni
PRESENTATION ON MOUNTAIN DEW sheni
 
RSpec 2 Best practices
RSpec 2 Best practicesRSpec 2 Best practices
RSpec 2 Best practices
 
MM072015
MM072015MM072015
MM072015
 
Mobile + Cloud+ Big Data = Digital Win
Mobile + Cloud+ Big Data = Digital WinMobile + Cloud+ Big Data = Digital Win
Mobile + Cloud+ Big Data = Digital Win
 

Ähnlich wie Controller specs

Euruko 2009 - DataObjects
Euruko 2009 - DataObjectsEuruko 2009 - DataObjects
Euruko 2009 - DataObjectsDirkjan Bussink
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overviewYehuda Katz
 
RubyBarCamp “Полезные gems и plugins”
RubyBarCamp “Полезные gems и plugins”RubyBarCamp “Полезные gems и plugins”
RubyBarCamp “Полезные gems и plugins”apostlion
 
浜松Rails3道場 其の参 Controller編
浜松Rails3道場 其の参 Controller編浜松Rails3道場 其の参 Controller編
浜松Rails3道場 其の参 Controller編Masakuni Kato
 
QConSP 2015 - Dicas de Performance para Aplicações Web
QConSP 2015 - Dicas de Performance para Aplicações WebQConSP 2015 - Dicas de Performance para Aplicações Web
QConSP 2015 - Dicas de Performance para Aplicações WebFabio Akita
 
Automated testing with RSpec
Automated testing with RSpecAutomated testing with RSpec
Automated testing with RSpecNascenia IT
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Railsrstankov
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For BeginnersJonathan Wage
 
Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)Joao Lucas Santana
 
What's Coming in Spring 3.0
What's Coming in Spring 3.0What's Coming in Spring 3.0
What's Coming in Spring 3.0Matt Raible
 
VPN Access Runbook
VPN Access RunbookVPN Access Runbook
VPN Access RunbookTaha Shakeel
 
Real Time App with Node.js
Real Time App with Node.jsReal Time App with Node.js
Real Time App with Node.jsJxck Jxck
 
Moving ActiveRecord objects to the boundaries of your domain
Moving ActiveRecord objects to the boundaries of your domainMoving ActiveRecord objects to the boundaries of your domain
Moving ActiveRecord objects to the boundaries of your domainPatrick Dougall
 
First Steps in Drupal Code Driven Development
First Steps in Drupal Code Driven DevelopmentFirst Steps in Drupal Code Driven Development
First Steps in Drupal Code Driven DevelopmentNuvole
 

Ähnlich wie Controller specs (20)

Well
WellWell
Well
 
BDD de fuera a dentro
BDD de fuera a dentroBDD de fuera a dentro
BDD de fuera a dentro
 
Euruko 2009 - DataObjects
Euruko 2009 - DataObjectsEuruko 2009 - DataObjects
Euruko 2009 - DataObjects
 
Rails 3 overview
Rails 3 overviewRails 3 overview
Rails 3 overview
 
RubyBarCamp “Полезные gems и plugins”
RubyBarCamp “Полезные gems и plugins”RubyBarCamp “Полезные gems и plugins”
RubyBarCamp “Полезные gems и plugins”
 
浜松Rails3道場 其の参 Controller編
浜松Rails3道場 其の参 Controller編浜松Rails3道場 其の参 Controller編
浜松Rails3道場 其の参 Controller編
 
Play!ng with scala
Play!ng with scalaPlay!ng with scala
Play!ng with scala
 
QConSP 2015 - Dicas de Performance para Aplicações Web
QConSP 2015 - Dicas de Performance para Aplicações WebQConSP 2015 - Dicas de Performance para Aplicações Web
QConSP 2015 - Dicas de Performance para Aplicações Web
 
Why ruby
Why rubyWhy ruby
Why ruby
 
Automated testing with RSpec
Automated testing with RSpecAutomated testing with RSpec
Automated testing with RSpec
 
Ruby/Rails
Ruby/RailsRuby/Rails
Ruby/Rails
 
Having Fun with Play
Having Fun with PlayHaving Fun with Play
Having Fun with Play
 
Ruby gems
Ruby gemsRuby gems
Ruby gems
 
Doctrine For Beginners
Doctrine For BeginnersDoctrine For Beginners
Doctrine For Beginners
 
Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)Desenvolvimento web com Ruby on Rails (parte 3)
Desenvolvimento web com Ruby on Rails (parte 3)
 
What's Coming in Spring 3.0
What's Coming in Spring 3.0What's Coming in Spring 3.0
What's Coming in Spring 3.0
 
VPN Access Runbook
VPN Access RunbookVPN Access Runbook
VPN Access Runbook
 
Real Time App with Node.js
Real Time App with Node.jsReal Time App with Node.js
Real Time App with Node.js
 
Moving ActiveRecord objects to the boundaries of your domain
Moving ActiveRecord objects to the boundaries of your domainMoving ActiveRecord objects to the boundaries of your domain
Moving ActiveRecord objects to the boundaries of your domain
 
First Steps in Drupal Code Driven Development
First Steps in Drupal Code Driven DevelopmentFirst Steps in Drupal Code Driven Development
First Steps in Drupal Code Driven Development
 

Kürzlich hochgeladen

How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesBernd Ruecker
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integrationmarketing932765
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxfnnc6jmgwh
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.Curtis Poe
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationKnoldus Inc.
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxLoriGlavin3
 

Kürzlich hochgeladen (20)

How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
QCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architecturesQCon London: Mastering long-running processes in modern architectures
QCon London: Mastering long-running processes in modern architectures
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.How AI, OpenAI, and ChatGPT impact business and software.
How AI, OpenAI, and ChatGPT impact business and software.
 
Data governance with Unity Catalog Presentation
Data governance with Unity Catalog PresentationData governance with Unity Catalog Presentation
Data governance with Unity Catalog Presentation
 
Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptxA Deep Dive on Passkeys: FIDO Paris Seminar.pptx
A Deep Dive on Passkeys: FIDO Paris Seminar.pptx
 

Controller specs

  • 7. RSpec Tips • Configuration: Color, Verbose • Alias bundle exec • description text should build the user story • add comments to your end statements
  • 9. Alias Bundle exec alias brspec="bundle exec rspec" alias be="bundle exec"
  • 10. Description Text builds a User Story TagsController when authorized User (admin) the DELETE #destroy action behaves like a 302 redirect request action redirects to :back (root_path)
  • 12. RSPec Gotchas • Scoping is weird it_behaves_like "a 302 redirect request action", ":back (root_path)" do let!(:put_update) {put :update, id: @user.id, user: @user_attributes} let(:redirect_path) {root_path} end • Relish Docs
  • 14. How to RSpec OO BB Object Oriented Black Box • Given (Context) • When (Event) • Then (Expected Result)
  • 16. Given • Session • Domain Object Layer status • Params
  • 17. When • HTTP Request with Params
  • 18. Then • Flash Messages • Assigns Instance Variables (decorators) • Domain Object Layer Changes
  • 19. Keeping it DRY • before Hooks (given) • let (when) • shared examples
  • 20. before :example before :example do @admin = create(:admin) session[:user_id] = @admin.id end
  • 21. let :example let!(:post_create) {post :create, user: @user_attributes} let(:redirect_path) {root_path}
  • 22. shared examples: 3 types of RESTful responses • successful GET action • redirect 302 action • unauthorized action 302 redirect
  • 23. successful GET action RSpec.shared_examples_for 'an unauthorized action' do it "responds redirect with an HTTP 302 status code" do expect(response).to be_redirect expect(response).to have_http_status(:found) end it "provides a flash alert message" do expect(flash[:warning]).to_not be_nil end it "redirects to login_path" do expect(response).to redirect_to login_path end end
  • 24. redirect 302 action RSpec.shared_examples_for "a 302 redirect request action" do |path_name| it "responds with a redirect HTTP 302 status code" do expect(response).to be_redirect expect(response).to have_http_status(:found) end it "redirects to #{path_name}" do expect(response).to redirect_to redirect_path end end
  • 25. unauthorized action 302 redirect RSpec.shared_examples_for 'an unauthorized action' do it "responds redirect with an HTTP 302 status code" do expect(response).to be_redirect expect(response).to have_http_status(:found) end it "provides a flash alert message" do expect(flash[:warning]).to_not be_nil end it "redirects to login_path" do expect(response).to redirect_to login_path end end
  • 26. Overall Structure of a Controller Spec
  • 27. require 'support/controller_helper' describe UsersController do context 'when unauthorized (no User)' do describe "the GET #new action" do end # describe "the GET #new action" do describe "the POST #create action" do context "is provided valid User params and" do end # context "is provided valid User params and" do context "is provided invalid User params and" do end # context "is provided invalid User params and" do end # describe "the POST #create action" do describe "the GET #show action" do end # describe "the GET #show action" do end # context 'when unauthorized (no User signed in)' do
  • 28. context 'when authorized (Admin User)' do describe "the GET #index action" do end #describe "the GET #index action" do describe "the PUT #update action" do context "is provided valid user params and" do end # "is provided valid user params and" do context "is provided invalid user params and" do end # "is provided invalid user params and" do end # "the PUT #update action" do end # context 'when authorized (Admin User)' do end
  • 30. Unauthorized Action describe "the GET #show action" do before :example do @user = create(:user) end it_behaves_like 'an unauthorized action' do let!(:get_show) {get :show, {id: @user.id}} end end # describe "the GET #show action" do
  • 32. GET #show describe "the GET #show action" do before :example do @user = create(:user) end it_behaves_like "a successful GET action", :show do let!(:get_show) {get :show, {id: @user.id}} end let(:get_show) {get :show, {id: @user.id}} it "assigns a valid UserDecorator of to @user" do get_show @decorated_user = UserDecorator.new @user expect(assigns(:user)).to be_kind_of(UserDecorator) expect(assigns(:user)).to eq(@decorated_user) end end # describe "the GET #show action" do
  • 33. GET #index describe "the GET #index action" do it_behaves_like "a successful GET action", :index do let!(:get_index) {get :index} end let(:get_index) {get :index}
  • 34. GET #index con'd it "loads the users in the current users, current region" do region = create(:region) user1, user2 = create(:user), create(:user) [@admin, user1, user2].each do |u| u.add_to_region! region u.current_region = region u.save end get_index expect(assigns(:users)).to match_array([@admin.reload, user1.reload, user2.reload]) end end #describe "the GET #index action" do
  • 35. GET #new describe "the GET #new action" do it_behaves_like "a successful GET action", :new do let!(:get_new) {get :new} end let!(:get_new) {get :new} it "assigns a unsaved User to @user" do expect(assigns(:user)).to be_kind_of(User) expect(assigns(:user)).to respond_to(:id).with(nil) end end # describe "the GET #new action" do
  • 36. POST #create describe "the POST #create action" do before :example do @user_attributes = attributes_for(:user) request.env["HTTP_REFERER"] = root_path end let(:post_create) {post :create, user: @user_attributes}
  • 37. POST #create con't context "is provided valid User params and" do it_behaves_like "a 302 redirect request action", ':back (to root_path)' do let!(:post_create) {post :create, user: @user_attributes} let(:redirect_path) {root_path} end it "creates a user" do expect { post_create }.to change(User, :count).by(1) end it "provides a flash success message" do post_create expect(flash[:success]).to_not be_nil end end # context "is provided valid User params and" do
  • 38. POST #create con't con't context "is provided invalid User params and" do before :example do @user_attributes = attributes_for(:user) User.create @user_attributes end it_behaves_like "a 302 redirect request action", 'new_user_path' do let!(:post_create) {post :create, user: @user_attributes} let(:redirect_path) {new_user_path} end it "fails to create a new user" do expect { post :create, user: @user_attributes }.not_to change(User, :count) end it "provides a flash danger message" do post_create expect(flash[:danger]).to_not be_nil end end # context "is provided invalid User params and" do end # describe "the POST #create action" do
  • 39. GET #edit describe "the GET #edit action" do before :example do @user = create(:user) end it_behaves_like "a successful GET action", :edit do let!(:get_edit) {get :edit, {id: @user.id}} end let(:get_edit) {get :edit, {id: @user.id}} it "loads all of the roles from User class into @roles" do roler = class_double("User") allow(roler).to receive(:roles).and_return([:worker, :manager, :organizer, :moderator, :admin]) get_edit expect(assigns(:roles)).to match_array([:worker, :manager, :organizer, :moderator, :admin]) end
  • 40. GET #edit c on't it "loads all of the regions from Region class into @regions" do region1, region2 = create(:region), create(:region) get_edit expect(assigns(:regions)).to match_array([region1, region2]) end it "assigns valid UserDecorator to @user" do get_edit @decorated_user = UserDecorator.new @user expect(assigns(:user)).to be_kind_of(UserDecorator) expect(assigns(:user)).to eq(@decorated_user) end end # describe "the GET #edit action" do
  • 41. PATCH #update describe "the PUT #update action" do let(:put_update) {put :update, id: @user.id, user: @user_attributes} context "is provided valid user params and" do before :example do @user_attributes = attributes_for(:user).merge({email: "vengeful_spirit@example.com"}) @user = User.create @user_attributes.merge({email: "sneaky_jugger@example.com"}) end it_behaves_like "a 302 redirect request action", "@user" do let!(:put_update) {put :update, id: @user.id, user: @user_attributes} let(:redirect_path) {@user} end
  • 42. PATCH #update con't it "changes user email attribute" do expect(@user.reload.email).to eq("sneaky_jugger@example.com") put_update expect(@user.reload.email).to eq("vengeful_spirit@example.com") end it "provides a flash success message" do put_update expect(flash[:success]).to_not be_nil end end # "is provided valid user params and" do
  • 43. PATCH #update con't con't context "is provided invalid user params and" do before :example do @user_attributes = attributes_for(:user).merge({email: "vengeful_spirit.example.com"}) @user = User.create @user_attributes.merge({email: "sneaky_jugger@example.com"}) request.env["HTTP_REFERER"] = root_path end it_behaves_like "a 302 redirect request action", ":back (root_path)" do let!(:put_update) {put :update, id: @user.id, user: @user_attributes} let(:redirect_path) {root_path} end
  • 44. PATCH #update con't con't con't it "fails to change user email attribute" do expect(@user.reload.email).to eq("sneaky_jugger@example.com") put_update expect(@user.reload.email).to eq("sneaky_jugger@example.com") end it "provides a flash danger message" do put_update expect(flash[:danger]).to_not be_nil end end # "is provided invalid user params and" do end # "the PUT #update action" do
  • 45. DELETE #destroy describe "the DELETE #destroy action" do before :example do @tag = create(:tag) request.env["HTTP_REFERER"] = tags_path end let(:delete_destroy) {delete :destroy, id: @tag.id } it "destroys @tag" do expect {delete_destroy}.to change(Tag, :count).by(-1) end it_behaves_like "a 302 redirect request action", "tags_path (:back)" do let!(:delete_destroy) {delete :destroy, id: @tag.id } let(:redirect_path) {tags_path} end end
  • 46. Resources • Everyday Rails: How I learned to test my Rails applications • Relish: RSpec Docs • Code School: Testing with RSpec • Code Examples