Patrick McCafferty
2005-Aug-21 07:32 UTC
Reverse validation in testing, no validation at all in development
I''m currently creating an item instantiation system, where there are prototype items in a database that are used as templates for "real" items. Real items are, of course, owned by users and keep track of what prototype they came from. So: class ItemInstance < ActiveRecord::Base belongs_to :user belongs_to :item_prototype validates_presence_of :name, :shard_cost, :level, :item_type, :user_id, :item_prototype_id validates_length_of :name, :within => 2..40 validates_inclusion_of :shard_cost, :in => 1..9999 validates_inclusion_of :level, :in => 1..999 validates_inclusion_of :kind, :in => %w( weapon armor ) validates_associated :user validates_associated :item_prototype end But the weirdness comes when I: create an instance from the scaffold /new action: It lets me put ANYTHING in user_id and item_prototype_id. It won''t let me leave them out, so THAT part is working, but it doesn''t validate the associated ones at all. create an instance from testing: It''s bizarro validation. Here''s what I mean: def test_create num_item_instances = ItemInstance.count assert_not_nil ItemPrototype.find(1) assert_not_nil User.find(1) post :create, :item_instance => {:name => "baz", :user_id => "1", :item_prototype_id => "1", :shard_cost => "20", :level => "12", :kind => "armor", :is_blueprint => "1"} assert_response :redirect assert_redirected_to :action => ''list'' assert_equal num_item_instances + 1, ItemInstance.count end This test fails: 1) Failure: test_create(ItemInstancesControllerTest) [/usr/lib/ruby/gems/1.8/gems/actionpack-1.9.1/lib/ action_controller/assertions.rb:63:in `assert_response'' ./test/functional/item_instances_controller_test.rb:59:in `test_create'']: Expected response to be a <:redirect>, but was <200> And then testing to see if validation prevents me from creating a bad record: def test_create_bad # Now test userid validation assert_raise(ActiveRecord::RecordNotFound) { User.find(24395) } post :create, :item_instance => {:name => "bee", :user_id => "24395", :item_prototype_id => "1", :shard_cost => "20", :level => "12", :kind => "armor", :is_blueprint => "1"} assert_response :success assert_template ''new'' assert_invalid_column_on_record "item_instance", :user_id end PASSES VALIDATION (failing ITS test): 2) Failure: test_create_bad(ItemInstancesControllerTest) [/usr/lib/ruby/gems/1.8/gems/actionpack-1.9.1/lib/ action_controller/assertions.rb:63:in `assert_response'' ./test/functional/item_instances_controller_test.rb:73:in `test_create_bad'']: Expected response to be a <:success>, but was <302> I don''t get this. Why is it that testing produces different results than the development, for one thing? And why is validation functioning in reverse? Like my previous problem, I''m sure I''m just missing something obvious in how it should work. Thanks for the help!
Patrick McCafferty
2005-Aug-21 17:13 UTC
Re: Reverse validation in testing, no validation at all in development
A correction. In my development code the same "bizarro" validation is occurring, i.e. it''s failing to validate the user_ids that exist and validating the ones that don''t. I was just counting ids wrong... Am I just missing how validates_associated should be working? On 8/21/05, Patrick McCafferty <ryouga-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> I''m currently creating an item instantiation system, where there are > prototype items in a database that are used as templates for "real" > items. > > Real items are, of course, owned by users and keep track of what > prototype they came from. So: > > class ItemInstance < ActiveRecord::Base > belongs_to :user > belongs_to :item_prototype > > > validates_presence_of :name, :shard_cost, :level, :item_type, :user_id, > :item_prototype_id > validates_length_of :name, :within => 2..40 > validates_inclusion_of :shard_cost, :in => 1..9999 > validates_inclusion_of :level, :in => 1..999 > validates_inclusion_of :kind, :in => %w( weapon armor ) > validates_associated :user > validates_associated :item_prototype > end > > But the weirdness comes when I: > > create an instance from the scaffold /new action: > It lets me put ANYTHING in user_id and item_prototype_id. It won''t > let me leave them out, so THAT part is working, but it doesn''t > validate the associated ones at all. > > create an instance from testing: > It''s bizarro validation. Here''s what I mean: > > def test_create > num_item_instances = ItemInstance.count > assert_not_nil ItemPrototype.find(1) > assert_not_nil User.find(1) > > post :create, :item_instance => {:name => "baz", :user_id => > "1", :item_prototype_id => "1", :shard_cost => "20", :level => > "12", :kind => "armor", :is_blueprint => "1"} > > assert_response :redirect > assert_redirected_to :action => ''list'' > > assert_equal num_item_instances + 1, ItemInstance.count > end > > This test fails: > 1) Failure: > test_create(ItemInstancesControllerTest) > [/usr/lib/ruby/gems/1.8/gems/actionpack-1.9.1/lib/ > action_controller/assertions.rb:63:in `assert_response'' > ./test/functional/item_instances_controller_test.rb:59:in > `test_create'']: > Expected response to be a <:redirect>, but was <200> > > And then testing to see if validation prevents me from creating a bad > record: > def test_create_bad > # Now test userid validation > assert_raise(ActiveRecord::RecordNotFound) { > User.find(24395) > } > > post :create, :item_instance => {:name => "bee", :user_id => > "24395", :item_prototype_id => "1", :shard_cost => "20", :level => > "12", :kind => "armor", :is_blueprint => "1"} > > assert_response :success > assert_template ''new'' > > assert_invalid_column_on_record "item_instance", :user_id > end > > PASSES VALIDATION (failing ITS test): > 2) Failure: > test_create_bad(ItemInstancesControllerTest) > [/usr/lib/ruby/gems/1.8/gems/actionpack-1.9.1/lib/ > action_controller/assertions.rb:63:in `assert_response'' > ./test/functional/item_instances_controller_test.rb:73:in > `test_create_bad'']: > Expected response to be a <:success>, but was <302> > > I don''t get this. Why is it that testing produces different results > than the development, for one thing? And why is validation > functioning in reverse? > > Like my previous problem, I''m sure I''m just missing something obvious > in how it should work. > > Thanks for the help! >
Patrick McCafferty
2005-Aug-21 18:03 UTC
Re: Reverse validation in testing, no validation at all in development - RESOLVED
On 8/22/05, Patrick McCafferty <ryouga-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> A correction. In my development code the same "bizarro" validation is > occurring, i.e. it''s failing to validate the user_ids that exist and > validating the ones that don''t. I was just counting ids wrong... > > Am I just missing how validates_associated should be working?The proper response here is "Yes, you are in fact missing how it should be working. Also, you have found a bug in your code at the same time."> On 8/21/05, Patrick McCafferty <ryouga-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote: > > I''m currently creating an item instantiation system, where there are > > prototype items in a database that are used as templates for "real" > > items. > > > > Real items are, of course, owned by users and keep track of what > > prototype they came from. So: > > > > class ItemInstance < ActiveRecord::Base > > belongs_to :user > > belongs_to :item_prototype > > > > > > validates_presence_of :name, :shard_cost, :level, :item_type, :user_id, > > :item_prototype_id > > validates_length_of :name, :within => 2..40 > > validates_inclusion_of :shard_cost, :in => 1..9999 > > validates_inclusion_of :level, :in => 1..999 > > validates_inclusion_of :kind, :in => %w( weapon armor ) > > validates_associated :user > > validates_associated :item_prototype > > end > > > > But the weirdness comes when I: > > > > create an instance from the scaffold /new action: > > It lets me put ANYTHING in user_id and item_prototype_id. It won''t > > let me leave them out, so THAT part is working, but it doesn''t > > validate the associated ones at all. > > > > create an instance from testing: > > It''s bizarro validation. Here''s what I mean: > > > > def test_create > > num_item_instances = ItemInstance.count > > assert_not_nil ItemPrototype.find(1) > > assert_not_nil User.find(1) > > > > post :create, :item_instance => {:name => "baz", :user_id => > > "1", :item_prototype_id => "1", :shard_cost => "20", :level => > > "12", :kind => "armor", :is_blueprint => "1"} > > > > assert_response :redirect > > assert_redirected_to :action => ''list'' > > > > assert_equal num_item_instances + 1, ItemInstance.count > > end > > > > This test fails: > > 1) Failure: > > test_create(ItemInstancesControllerTest) > > [/usr/lib/ruby/gems/1.8/gems/actionpack-1.9.1/lib/ > > action_controller/assertions.rb:63:in `assert_response'' > > ./test/functional/item_instances_controller_test.rb:59:in > > `test_create'']: > > Expected response to be a <:redirect>, but was <200> > > > > And then testing to see if validation prevents me from creating a bad > > record: > > def test_create_bad > > # Now test userid validation > > assert_raise(ActiveRecord::RecordNotFound) { > > User.find(24395) > > } > > > > post :create, :item_instance => {:name => "bee", :user_id => > > "24395", :item_prototype_id => "1", :shard_cost => "20", :level => > > "12", :kind => "armor", :is_blueprint => "1"} > > > > assert_response :success > > assert_template ''new'' > > > > assert_invalid_column_on_record "item_instance", :user_id > > end > > > > PASSES VALIDATION (failing ITS test): > > 2) Failure: > > test_create_bad(ItemInstancesControllerTest) > > [/usr/lib/ruby/gems/1.8/gems/actionpack-1.9.1/lib/ > > action_controller/assertions.rb:63:in `assert_response'' > > ./test/functional/item_instances_controller_test.rb:73:in > > `test_create_bad'']: > > Expected response to be a <:success>, but was <302> > > > > I don''t get this. Why is it that testing produces different results > > than the development, for one thing? And why is validation > > functioning in reverse? > > > > Like my previous problem, I''m sure I''m just missing something obvious > > in how it should work. > > > > Thanks for the help! > > >
Nicholas Seckar
2005-Aug-21 18:06 UTC
Re: Re: Reverse validation in testing, no validation at all in development
Hi Patrick, Your validations ought to be tested in your unit tests (test/unit) rather than functional tests. Well, your functional tests should try to create and save invalid objects too, but thinks work better if you first use your unit tests to ensure that your validations work properly. Generally you''ll get better errors, and it is an easier environment to debug models from. If you find validation tests frustratingly verbose, check out my AR test helper: http://www.bigbold.com/snippets/posts/show/573 Using it, meanial tests such as # Test to make sure the association tables are set up, # and that the associated models can be loaded def test_associations_work assert project.users && project.users.find_all assert project.owner end def test_validations_for_name project.name = ''BigProject'' assert ! project.valid? assert_matches /already taken/, project.errors.on(:name) [nil, ''''].each dp |name| project.name = name assert ! project.valid? assert_matches /can''t be blank/, project.errors.on(:name) end project.name = ''new name'' assert project.valid? assert project.save # make sure the database agrees with us end Can be written as check_associations %w(users owner) check_validations_for :name do invalid ''BigProject'', /already taken/ [nil, ''''].each {|name| invalid name, /can''t be blank/} valid ''new name'' end Dry, eh? ;-)
Patrick McCafferty
2005-Aug-21 19:18 UTC
Re: Re: Reverse validation in testing, no validation at all in development
Ah, that helps a lot. Thanks :) Yeah, I was just fixing the failed tests when I added validation in the model, which focused me on the functionals first (since generated tests do nothing in unit and attempt to post create in the functionals) I''ll check out your helper. Thanks a lot! On 8/22/05, Nicholas Seckar <nseckar-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> Hi Patrick, > > Your validations ought to be tested in your unit tests (test/unit) > rather than functional tests. > > Well, your functional tests should try to create and save invalid > objects too, but thinks work better if you first use your unit tests to > ensure that your validations work properly. Generally you''ll get better > errors, and it is an easier environment to debug models from. > > If you find validation tests frustratingly verbose, check out my AR test > helper: > > http://www.bigbold.com/snippets/posts/show/573 > > Using it, meanial tests such as > > # Test to make sure the association tables are set up, > # and that the associated models can be loaded > def test_associations_work > assert project.users && project.users.find_all > assert project.owner > end > > def test_validations_for_name > project.name = ''BigProject'' > assert ! project.valid? > assert_matches /already taken/, project.errors.on(:name) > > [nil, ''''].each dp |name| > project.name = name > assert ! project.valid? > assert_matches /can''t be blank/, project.errors.on(:name) > end > > project.name = ''new name'' > assert project.valid? > assert project.save # make sure the database agrees with us > end > > Can be written as > > check_associations %w(users owner) > > check_validations_for :name do > invalid ''BigProject'', /already taken/ > [nil, ''''].each {|name| invalid name, /can''t be blank/} > valid ''new name'' > end > > Dry, eh? ;-) > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >