Forum: RSpec doesn't rspec check the existence of template file

Posted by Sean Liu (foreverman)
on 2011-08-25 13:33
(Received via mailing list)
Hey,

I am using rspec (1.3.0) and rspec-rails (1.3.2) for my current rails2
project, I found that in my controller test, rspec doesn't check the
existence of view template. For example,
it "should render show template" do
  get :show
  response.should render_template :show
end

The above controller test will pass even the 'show' template doesn't
exist.

I am curious if this is a bug or I did something wrong.

Thanks.
Posted by David Chelimsky (Guest)
on 2011-08-25 15:42
(Received via mailing list)
On Aug 23, 2011, at 5:02 AM, foreverman wrote:

> The above controller test will pass even the 'show' template doesn't
> exist.
>
> I am curious if this is a bug or I did something wrong.


Neither. There's a bit of history here so bear with me.

The names used in Rails for the different kinds of tests it offers do 
not align with the names we used to use before Rails came along. Here 
are some older definitions (which are the ones to which I subscribe, but 
that doesn't mean "they are the right ones"):

Unit test: specifies behavior of an object in isolation.
Integration test: specifies behavior of two or more objects in which 
there are at least two bits of non-trivial behavior.
Functional test: specifies how the application behaves (from a user 
perspective, or close facsimile)
System test: specifies how a system of applications behave

These each cover progressively wider scope: unit, integration, 
functional, system.

Based on that nomenclature, what Rails calls unit, functional, and 
integration tests are really integration (model + db), integration (mvc 
+ db), and functional tests (mvc + db + routing/sessions).

The rspec-rails gem aims to support the more traditional scopes by 
offering unit tests for controllers and views. This is what you've come 
up against: a controller spec is intended to be a unit test for the 
controller. To support this, rspec-rails (1.x) does not actually render 
any views at all. If the spec says the controller should render 
"foo/bar", and the controller renders "foo/bar", then the example passes 
whether or not the view exists. In a BDD process, we work from the 
outside-in, so before the controller spec exists, there would be a 
failing "integration spec" (which were called that to align with Rails' 
nomenclature in rspec-rails-1, but are called "request specs" in 
rspec-rails-2 - perhaps we should really call these "functional specs", 
but that might just make things more confusing). That serves two 
purposes: it describes the behavior from a user perspective (when I 
submit this form with valid data, then xyz happens), and it also 
provides test coverage that prove
 s that the isolated parts specified in model, view, controller, and 
helper specs all play nice together.

If you prefer to treat controller specs as Rails functional tests (which 
are mvc + db integration specs, but not functional tests since they 
bypass the router (sort of) and sessions (sort of)), you can tell 
rspec-rails-1 to render views with the "integrate_views" declaration 
("render_views" in rspec-rails-2):

# globally
Spec::Runner::configure do |c|
  c.integrate_views
end

or

# for one spec
describe ThingsController do
  integrate_views
  ...
end

HTH,
David
Posted by Phillip Koebbe (pkoebbe)
on 2011-08-25 17:03
(Received via mailing list)
On 2011-08-25 7:04 AM, David Chelimsky wrote:
>> end
> Unit test: specifies behavior of an object in isolation.
> Integration test: specifies behavior of two or more objects in which there are 
at least two bits of non-trivial behavior.
> Functional test: specifies how the application behaves (from a user perspective, 
or close facsimile)
> System test: specifies how a system of applications behave
>
> These each cover progressively wider scope: unit, integration, functional, 
system.
>
> Based on that nomenclature, what Rails calls unit, functional, and integration 
tests are really integration (model + db), integration (mvc + db), and functional 
tests (mvc + db + routing/sessions).
>
> The rspec-rails gem aims to support the more traditional scopes by offering unit 
tests for controllers and views. This is what you've come up against: a controller 
spec is intended to be a unit test for the controller. To support this, 
rspec-rails (1.x) does not actually render any views at all. If the spec says the 
controller should render "foo/bar", and the controller renders "foo/bar", then the 
example passes whether or not the view exists. In a BDD process, we work from the 
outside-in, so before the controller spec exists, there would be a failing 
"integration spec" (which were called that to align with Rails' nomenclature in 
rspec-rails-1, but are called "request specs" in rspec-rails-2 - perhaps we should 
really call these "functional specs", but that might just make things more 
confusing). That serves two purposes: it describes the behavior from a user 
perspective (when I submit this form with valid data, then xyz happens), and it 
also provides test coverage that pro
 ve
>
> # for one spec
> describe ThingsController do
>    integrate_views
>    ...
> end
>
> HTH,
> David

Just throwing out my own experience with this issue.

I tried the integrate_views approach, but then had to mock so much stuff
so the view wouldn't generate errors it became an incredible burden. But
I still wanted to know that I was rendering the right view at the right
time. I came up with something that is simple, albeit a bit verbose:

In the controller, I explicitly call render (meaning, I don't let Rails
magic happen):

def index
   render :index
end

Then in the controller test, I set an expectation:

describe 'get index' do
   it 'should render the index template' do
     controller.should_receive(:render).with(:index)
     get :index
   end
end

Phillip
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.