RSpec controller tests

28 views
Skip to first unread message

Chris McCann

unread,
Jan 11, 2014, 1:53:26 PM1/11/14
to sdr...@googlegroups.com
SD Ruby,

Over the holidays I embarked on a long-needed upgrade of the first Rails app I built, taking it from 2.3 to 3.1.  I plan to move it to 4.0 by the time I'm done.

Since this app was created over 6 years ago, before I understood the value of having test coverage, it has very little.  I've been remedying that via RSpec (2.14) and FactoryGirl and I'm pleased with the progress I've made and even discovered some bugs that weren't apparent pre-test.

The app is rather large and I need to get this upgrade done quickly since my customers are clamoring for more features.  I'm trying to balance basic "sanity checking" test coverage with the need for speed.  

I use simple_navigation to provide the links between the main menus and controller actions.  I thought it would be worthwhile to gin-up a bunch of request specs for the URLs that the menu links hit.  It seemed to me I'd at least have a basic "does the page for that menu link blow up?" scenario as a rudimentary check of the app.  But that doesn't seem to work the way I expected.

For example, hitting a URL via a request spec and checking for a 200 status passes.  But if I go to that same page in the browser I find vestiges of rails 2.3 that have been removed, like "error_messages_for" and the page throws an error.  

So I'm getting a false positive on the request spec -- how come?  Perhaps my understanding of what a request spec provides is flawed but I assumed an error in the page wouldn't allow the spec to pass.

My next attempt was to create controller specs for the controllers hit by the menus.  I use a before_filter in application_controller to set the current chapter and in trying to check that value is assigned isn't working.  

In the snippet below MemberController < ApplicationController.  The expect fails because the assigns(:chapter) returns nil.

require 'spec_helper'

describe MemberController do
  before :each do
    @chapter = FactoryGirl.create(:chapter)
    controller.stub!(:current_chapter).and_return(@chapter)
  end

  describe "GET my_home" do
    it "assigns @chapter" do
      get :my_home
      expect(assigns(:chapter)).to eq @chapter
    end
  end
end

I'm a n00bie with RSpec so perhaps my understanding is flawed.  How should this be setup?  Is there a better way?

Thanks,

Chris

Alex Boster

unread,
Jan 11, 2014, 2:04:55 PM1/11/14
to sdr...@googlegroups.com
Well, you are testing your controller here and probably your controller IS fine, if I had to guess (as is your controller test). The old RSpec “request” tests are now “feature” test and those are the more-full-stack-ish tests that would most likely show the errors you encounter in the browser. 

Put the capybara gem in the :test stanza of your Gemfile, then create the /spec/features directory. You can then make, for example, a spec like:

require 'spec_helper'

feature "Homepage" do

  context "Not logged in" do
    scenario "Correct elements should be visible on homepage" do
      visit root_path
      page.should have_content "Create an account"
      page.should_not have_selector("#adwords-signup-conversion-js")
      page.should_not have_selector("#facebook-signup-conversion-js")
    end
  end
end

This is just an example, but probably your error requires the view to actually render, and it’s a test like this that will do that. 

AB

--
--
SD Ruby mailing list
sdr...@googlegroups.com
http://groups.google.com/group/sdruby
---
You received this message because you are subscribed to the Google Groups "SD Ruby" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sdruby+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Alex Boster

unread,
Jan 11, 2014, 2:06:19 PM1/11/14
to sdr...@googlegroups.com
Rereading your email, I seem to have misunderstood several things you said. Whoopsie. Too little coffee this morning.

AB

On Jan 11, 2014, at 10:53 AM, Chris McCann <testf...@gmail.com> wrote:

Chris McCann

unread,
Jan 11, 2014, 2:14:35 PM1/11/14
to sdr...@googlegroups.com
No worries, Alex, I appreciate the feedback.  Now caffeinate, young man!


You received this message because you are subscribed to a topic in the Google Groups "SD Ruby" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/sdruby/P0aIMrF_TFA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to sdruby+un...@googlegroups.com.

Hillary Hueter

unread,
Jan 11, 2014, 4:56:59 PM1/11/14
to sdr...@googlegroups.com
There's a whole book by this guy Everyday Testing with Rails Aaron Sumner. But there's a short blog series by the same guy here. The factory girl syntax is older, but it uses rspec 2 syntax.

Everyday Rails Testing with RSpec: The book. But this 5 page blog series i found really useful, as he goes into controller and request testing with rspec http://everydayrails.com/2012/03/12/testing-series-intro.html.
If you do the test through capybara the test in a request test. I don't know a lot of details but the blog i linked to goes over it in the last chapter.

Or the test you have setup is fine, you just need to have a render_template validation. The current test just seems to be checking that the instance variable is assigned.

describe MemberController do
  before :each do
    @chapter = FactoryGirl.create(:chapter)
    controller.stub!(:current_chapter).and_return(@chapter)
  end

  describe "GET my_home" do
    it "assigns @chapter" do
      get :my_home
      expect(assigns(:chapter)).to eq @chapter
    end
   
 

  end
end



Hillary Hueter

unread,
Jan 11, 2014, 5:19:20 PM1/11/14
to sdr...@googlegroups.com
google posted before i could finish

also so you don't have to do FactoryGirl.blah for each factory you can add this to the configure block of your spec helper

RSpec.configure do |config|
  config.include FactoryGirl::Syntax::Methods
end

or you can add those lines as a file to your support folder and add this to the spec_helper before the configure block so that it will be loaded with your tests.

Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }


If you're going to test this through the controller you need to add render_views to the top of the controller test. This will render the view (where your error is happening) and as a result all tests will fail.

require 'spec_helper'

describe MemberController do
  render_views
  before :each do
    @chapter = create(:chapter) #After configuring rspec to include FactoryGirl::Syntax::Methods
    controller.stub!(:current_chapter).and_return(@chapter)
  end

  describe "GET my_home" do
    it "assigns @chapter" do
      get :my_home
      expect(assigns(:chapter)).to eq @chapter
    end

    it "renders the :my_home template" do
      get :my_home
      expect(response).to render_template :my_home
    end

  end
end

Not entirely related. but I like using the gem faker to populate data. It allows you to
Reply all
Reply to author
Forward
0 new messages