controller specs

47
Controller Specs Xander Miller @pareidoliax

Upload: alexander-miller

Post on 04-Aug-2015

191 views

Category:

Technology


0 download

TRANSCRIPT

Controller SpecsXander Miller@pareidoliax

What is Controller Testing?

Why Controller Test?

Tools

RSpecFactoryGirl

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 execalias brspec="bundle exec rspec"

alias be="bundle exec"

Description Text builds a User StoryTagsController 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 RSpecOO 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 :examplebefore :example do @admin = create(:admin) session[:user_id] = @admin.idend

let :examplelet!(: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 actionRSpec.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 endend

redirect 302 actionRSpec.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 endend

unauthorized action 302 redirectRSpec.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 endend

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)' doend

Example Specs

Unauthorized Actiondescribe "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}} endend # describe "the GET #show action" do

Examples by RESTful Action

GET #showdescribe "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) endend # describe "the GET #show action" do

GET #indexdescribe "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]) endend #describe "the GET #index action" do

GET #newdescribe "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) endend # describe "the GET #new action" do

POST #createdescribe "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" doend # describe "the POST #create action" do

GET #editdescribe "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 con'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) endend # describe "the GET #edit action" do

PATCH #updatedescribe "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: "[email protected]"}) @user = User.create @user_attributes.merge({email: "[email protected]"}) 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("[email protected]") put_update expect(@user.reload.email).to eq("[email protected]") 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: "[email protected]"}) 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("[email protected]") put_update expect(@user.reload.email).to eq("[email protected]") 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" doend # "the PUT #update action" do

DELETE #destroydescribe "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} endend

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

[email protected]