SlideShare a Scribd company logo
1 of 47
Download to read offline
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

More Related Content

What's hot

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
 

What's hot (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
 

Viewers also liked (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
 

Similar to 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
 

Similar to 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
 

Recently uploaded

Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Neo4j
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentationphoebematthew05
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraDeakin University
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticscarlostorres15106
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr LapshynFwdays
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024The Digital Insurer
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
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
 

Recently uploaded (20)

Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024Build your next Gen AI Breakthrough - April 2024
Build your next Gen AI Breakthrough - April 2024
 
costume and set research powerpoint presentation
costume and set research powerpoint presentationcostume and set research powerpoint presentation
costume and set research powerpoint presentation
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Artificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning eraArtificial intelligence in the post-deep learning era
Artificial intelligence in the post-deep learning era
 
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort ServiceHot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
Hot Sexy call girls in Panjabi Bagh 🔝 9953056974 🔝 Delhi escort Service
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmaticsKotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
Kotlin Multiplatform & Compose Multiplatform - Starter kit for pragmatics
 
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
"Federated learning: out of reach no matter how close",Oleksandr Lapshyn
 
My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024My INSURER PTE LTD - Insurtech Innovation Award 2024
My INSURER PTE LTD - Insurtech Innovation Award 2024
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
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...
 

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