Fearless Fool
2012-Sep-10 21:51 UTC
[rspec-users] Drawing the line between controller and integration tests
I''m trying to understand what belongs -- and what doesn''t belong -- in controller tests and in integration tests. As a common example, assume I have a list of named widgets. Somewhere in my code, I want to verify that widget = FactoryGirl.create(:widget) get :index generates a page that has the string #{widget.name} somewhere therein. But is that a controller test or an integration test? As another example, assume a user must be logged on in order to access the widgets. I can test authentication and authorization separately, but is it considered necessary to write an integration test for this? Or is this something you''d verify at the controller level? Etc. I''m not looking for specific answers to the above as much as guiding principles, or at least pointers to same. Thanks! -- Posted via http://www.ruby-forum.com/.
Fearless Fool
2012-Sep-10 22:28 UTC
[rspec-users] Drawing the line between controller and integration tests
One addendum: One thing I''d specifically like to know is where/how do you test the *contents* of generated responses? That seems beyond the purview of a controller test, but it doesn''t require multiple transactions or cross-controller interactions that would require an integration test. -- Posted via http://www.ruby-forum.com/.
Mike Ossareh
2012-Sep-10 23:52 UTC
[rspec-users] Drawing the line between controller and integration tests
On Mon, Sep 10, 2012 at 2:51 PM, Fearless Fool <lists at ruby-forum.com> wrote:> I''m trying to understand what belongs -- and what doesn''t belong -- in > controller tests and in integration tests. > > As a common example, assume I have a list of named widgets. Somewhere > in my code, I want to verify that > > widget = FactoryGirl.create(:widget) > get :index > > generates a page that has the string #{widget.name} somewhere therein. > But is that a controller test or an integration test? >Having spent a majority of my time writing test cases I''ve found there are two main types, unit tests and integration tests. An integration test is called such because it crosses a logical boundary (either in code or over a socket, talking to a database, etc). Unit tests are usually self contained. In your case you''re talking about a "controller" test, if I try to fit that into my mental model I can see it as either an integration test or a unit test - and you just need to decide which you want to use. Usually I''ve found integration tests to have the best bang for buck in terms of stability and unit tests to be very very helpful in fixing bugs and alleviating poor performance in chunks of code. Assuming you had the following flow: 1. User posts a form 2. Controller creates a "widget" 3. Controller redirects user to a list with "widget.name" in it. You would be best served writing an integration test, imho. The fact it is testing the controller and the model is neither here nor there. Let us assume there are some functions that exist on Widget that are not directly called by an HTTP action - then you''d want a unit test. That is the following would be integration tests. Widget #new #update_attributes Where as the following may be unit tests: Widget #friendly_name #synchronize_to_external_service> As another example, assume a user must be logged on in order to access > the widgets. I can test authentication and authorization separately, > but is it considered necessary to write an integration test for this? > Or is this something you''d verify at the controller level? > > Etc. I''m not looking for specific answers to the above as much as > guiding principles, or at least pointers to same. Thanks! > > -- > Posted via http://www.ruby-forum.com/. > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20120910/3f61c3c3/attachment-0001.html>
J. B. Rainsberger
2012-Sep-11 14:25 UTC
[rspec-users] Drawing the line between controller and integration tests
On Mon, Sep 10, 2012 at 5:51 PM, Fearless Fool <lists at ruby-forum.com> wrote:> I''m trying to understand what belongs -- and what doesn''t belong -- in > controller tests and in integration tests. > > As a common example, assume I have a list of named widgets. Somewhere > in my code, I want to verify that > > widget = FactoryGirl.create(:widget) > get :index > > generates a page that has the string #{widget.name} somewhere therein. > But is that a controller test or an integration test? >What''s the controller''s responsibility here? I see two things: * choose the right view * assign the right values to the right variables Actually rendering the right page with the right text on it sounds like a view responsibility. Therefore, how to check that the controller chooses the right view and assigns the variables correctly? As another example, assume a user must be logged on in order to access> the widgets. I can test authentication and authorization separately, > but is it considered necessary to write an integration test for this? > Or is this something you''d verify at the controller level? >I find this slightly trickier. Again, what''s the controller''s responsibility? * ask to authenticate the user for certain routes * ask to authorize the user for certain routes It seems clear which tests to write for the controller, but I don''t want to have to check authentication and authorization for every example I run on a specific route. Therefore, check authentication for each route in its own test. Also, check authorization for each route in its own test. Bad news: this will result in a lot of duplication in tests; good news: I find it easy to remove this duplication into a single set of authentication and authorization checks. Imagine something like this: describe "authenticate the user" do ROUTES_REQUIRING_AUTHENTICATION = [?] ROUTES_REQUIRING_AUTHENTICATION.each do | route | example "when requesting the resource at route #{route}" do authentication_service.should_receive(?) get route end end end The authorization policy checks will be a bit more complicated, but at least you can gather them all in the same place for easy reference. Etc. I''m not looking for specific answers to the above as much as> guiding principles, or at least pointers to same. Thanks! >My guiding principles haven''t changed in almost 15 years: http://link.jbrains.ca/simple-design -- J. B. (Joe) Rainsberger :: http://www.jbrains.ca :: http://blog.thecodewhisperer.com Author, JUnit Recipes Free Your Mind to Do Great Work :: http://www.freeyourmind-dogreatwork.com -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20120911/23fc91dc/attachment.html>
Cynthia Kiser
2012-Sep-11 20:25 UTC
[rspec-users] Drawing the line between controller and integration tests
Quoting Fearless Fool <lists at ruby-forum.com>:> I''m trying to understand what belongs -- and what doesn''t belong -- in > controller tests and in integration tests. > > As a common example, assume I have a list of named widgets. Somewhere > in my code, I want to verify that > > widget = FactoryGirl.create(:widget) > get :index > > generates a page that has the string #{widget.name} somewhere therein. > But is that a controller test or an integration test?First, one of the other responses in this thread split the world into unit tests vs integration tests. For the most part, the tests generated by the Rails framework are all set up to be unit tests (provided you use mocks and stubs instead of the supporting objects that you are not directly testing in a particular file). In your example above, since you created the object instead of using a stub or mock, this is an integration test, not a straight unit test for the controller. This test could fail for reasons having nothing to do with the controller (e.g. you added a required field ot the widget model and forgot to update your factory) - that makes it an integration test. To make that into a controller unit test, you need to mock the widget and just test that the controller makes available an instance variable containing ''widget''. Then you need a view spec that provides a mock for the @widget variable and then makes sure that the view displays the widget name. Or, as one of the other people pointed out, make an integration test that does all of what you outlined above.> As another example, assume a user must be logged on in order to access > the widgets. I can test authentication and authorization separately, > but is it considered necessary to write an integration test for this? > Or is this something you''d verify at the controller level?I usually take the road mentioned by one of the other respondents and create a separate file containing my authorization tests. Because in that file I am only focusing on the return status from the request, I am more or less making unit tests for my authorization configuration.> One addendum: One thing I''d specifically like to know is where/how > do you test the *contents* of generated responses? That seems > beyond the purview of a controller test, but it doesn''t require > multiple transactions or cross-controller interactions that would > require an integration test.In a Rails context, you test the contents of the generated responses in view tests. -- Cynthia N. Kiser cnk at ugcs.caltech.edu