After *much* digging and playing around, I finally figured out how to unit test instance variables that are created by actions. It was more difficult than I expected. It seems like there should have been a more straight forward way to do this. Can someone enlighten me? A simplified and somewhat contrived example of what I am current doing: Thanks. Matt>># My Controller of interest for testing class RecipeController < ApplicationController def list @recipes = Recipe.find_all @categories = Category.find_all end end>># My test file require File.dirname(__FILE__) + ''/../test_helper'' require ''recipe_controller'' class RecipeControllerTest < Test::Unit::TestCase def setup @controller = RecipeController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new create_fixtures "recipes" create_fixtures "categories" end def test_list get :list # This step seems exessively complex, and took me a while to figure out my_inst_vars = @controller.instance_variable_get "@assigns" assert_equal( 5, my_inst_vars["recipes"].size ) assert_equal( 8, my_inst_vars["categories"].size ) end end
You could also add accessor functions to your controller: class RecipeController < ApplicationController def recipes return @recipes end def categories return @categories end end class RecipeControllerTest < Test::Unit::TestCase def test_list get :list assert_equal(5, @controller.recipes.size) assert_equal(8, @controller.categories.size) end end Pete. On Tue, 8 Mar 2005 22:34:57 -0600, Belorion <belorion-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> After *much* digging and playing around, I finally figured out how to > unit test instance variables that are created by actions. It was > more difficult than I expected. It seems like there should have been > a more straight forward way to do this. Can someone enlighten me? A > simplified and somewhat contrived example of what I am current doing: > > Thanks. > > Matt > > >> > # My Controller of interest for testing > class RecipeController < ApplicationController > def list > @recipes = Recipe.find_all > @categories = Category.find_all > end > end > > >> > # My test file > require File.dirname(__FILE__) + ''/../test_helper'' > require ''recipe_controller'' > > class RecipeControllerTest < Test::Unit::TestCase > def setup > @controller = RecipeController.new > @request = ActionController::TestRequest.new > @response = ActionController::TestResponse.new > create_fixtures "recipes" > create_fixtures "categories" > end > > def test_list > get :list > # This step seems exessively complex, and took me a while to figure out > my_inst_vars = @controller.instance_variable_get "@assigns" > > assert_equal( 5, my_inst_vars["recipes"].size ) > assert_equal( 8, my_inst_vars["categories"].size ) > end > end > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails > >
This is better written as: class RecipeController < ApplicationController attr_accessor :recipes, :categories end -- John Long http://wiseheartdesign.com Pete Bevin wrote:> You could also add accessor functions to your controller: > > class RecipeController < ApplicationController > def recipes > return @recipes > end > def categories > return @categories > end > end > > class RecipeControllerTest < Test::Unit::TestCase > def test_list > get :list > assert_equal(5, @controller.recipes.size) > assert_equal(8, @controller.categories.size) > end > end > > Pete. > > > On Tue, 8 Mar 2005 22:34:57 -0600, Belorion <belorion-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > >>After *much* digging and playing around, I finally figured out how to >>unit test instance variables that are created by actions. It was >>more difficult than I expected. It seems like there should have been >>a more straight forward way to do this. Can someone enlighten me? A >>simplified and somewhat contrived example of what I am current doing: >> >>Thanks. >> >>Matt >> >> >># My Controller of interest for testing >>class RecipeController < ApplicationController >> def list >> @recipes = Recipe.find_all >> @categories = Category.find_all >> end >>end >> >> >># My test file >>require File.dirname(__FILE__) + ''/../test_helper'' >>require ''recipe_controller'' >> >>class RecipeControllerTest < Test::Unit::TestCase >> def setup >> @controller = RecipeController.new >> @request = ActionController::TestRequest.new >> @response = ActionController::TestResponse.new >> create_fixtures "recipes" >> create_fixtures "categories" >> end >> >> def test_list >> get :list >> # This step seems exessively complex, and took me a while to figure out >> my_inst_vars = @controller.instance_variable_get "@assigns" >> >> assert_equal( 5, my_inst_vars["recipes"].size ) >> assert_equal( 8, my_inst_vars["categories"].size ) >> end >>end >>_______________________________________________ >>Rails mailing list >>Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org >>http://lists.rubyonrails.org/mailman/listinfo/rails >> >> > > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >
Belorion wrote:> After *much* digging and playing around, I finally figured out how to > unit test instance variables that are created by actions. It was > more difficult than I expected. It seems like there should have been > a more straight forward way to do this. Can someone enlighten me? A > simplified and somewhat contrived example of what I am current doing: > > def test_list > get :list > # This step seems exessively complex, and took me a while to figure out > my_inst_vars = @controller.instance_variable_get "@assigns" > > assert_equal( 5, my_inst_vars["recipes"].size ) > assert_equal( 8, my_inst_vars["categories"].size ) > end > endThese assertions test instance variables passed to the view from the controller: assert_template_has assert_template_has_no assert_assigned_equals See http://manuals.rubyonrails.com/read/chapter/28#page78 However, they don''t allow you to manipulate the instance variables. You can pull them directly from the response instead: def test_list assert_equal 5, @response.template.assigns[''recipes''].size assert_equal 8, @response.template.assigns[''categories''].size end Test::Unit::TestCase#assigns would be a convenient enhancement. def test_list assert_equal 5, assigns(:recipes).size assert_equal 8, assigns(:categories).size end protected def assigns(name) @response.template.assigns[name.to_s] end jeremy
> Test::Unit::TestCase#assigns would be a convenient enhancement. > > def test_list > assert_equal 5, assigns(:recipes).size > assert_equal 8, assigns(:categories).size > end > > protected > def assigns(name) > @response.template.assigns[name.to_s] > end > > jeremyThat looks like a perfect solution. Not sure why didn''t think of that myself! Though it still seems a little wierd that it isn''t more straighforward, like all the other unit testing in Rails. It''s so easy to check to see if an instance variable exists and is available to a template (as seen with assert_template_has, assert_template_has_no, & assert_assigned_equals), but so hard to actually peek at that variable. Thanks. Matt
Hi, Belorion wrote:>After *much* digging and playing around, I finally figured out how to >unit test instance variables that are created by actions. It was >more difficult than I expected. It seems like there should have been >a more straight forward way to do this. Can someone enlighten me? A >simplified and somewhat contrived example of what I am current doing: > > > def test_list > get :list > # This step seems exessively complex, and took me a while to figure out > my_inst_vars = @controller.instance_variable_get "@assigns" > > assert_equal( 5, my_inst_vars["recipes"].size ) > assert_equal( 8, my_inst_vars["categories"].size ) > end >end > >you can get them via "@controller.template_objects[''object_name'']" as well. That''s just a shorthand for the "@controller.template.assigns" proposed by Jeremy. Sebastian
> Test::Unit::TestCase#assigns would be a convenient enhancement. > > def test_list > assert_equal 5, assigns(:recipes).size > assert_equal 8, assigns(:categories).size > end > > protected > def assigns(name) > @response.template.assigns[name.to_s] > endGreat stuff. Checked in to SVN. -- David Heinemeier Hansson, http://www.basecamphq.com/ -- Web-based Project Management http://www.rubyonrails.org/ -- Web-application framework for Ruby http://www.loudthinking.com/ -- Broadcasting Brain
David Heinemeier Hansson <david-OiTZALl8rpK0mm7Ywyx6yg@public.gmane.org> wrote:> > def assigns(name) > > @response.template.assigns[name.to_s] > > end > > Great stuff. Checked in to SVN.This works well after a "process", but if I am redirected I seem to always get nil from this method. Is there a way to use assigns (or some other method) to get access to instance variables after a redirect? -- Regards, Stian Grytøyr
On Wed, 16 Mar 2005 09:57:37 +0100, Stian Grytøyr <sgrytoyr-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> David Heinemeier Hansson <david-OiTZALl8rpK0mm7Ywyx6yg@public.gmane.org> wrote: > > > > def assigns(name) > > > @response.template.assigns[name.to_s] > > > end > > > > Great stuff. Checked in to SVN. > > This works well after a "process", but if I am redirected I seem to always > get nil from this method. Is there a way to use assigns (or some other > method) to get access to instance variables after a redirect?a redirect sends an HTTP 302 response, so it''s a completely new controller with a new @request. After a redirect the instance variables aren''t there anymore.> -- > Regards, > Stian Grytøyr > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Cheers Koz
Michael Koziarski <koziarski-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> a redirect sends an HTTP 302 response, so it''s a completely new > controller with a new @request. After a redirect the instance > variables aren''t there anymore.OK, so the redirect isn''t actually "followed"? Is there a way to do that? I.e. "process whatever we are redirected to", so that we can check the new instance variables as well. -- Regards, Stian Grytøyr