I just created a simple model and started to write unit tests for it (I''ve cleaned out extraneous stuff). The migration is: class CreateMembers < ActiveRecord::Migration def self.up create_table :members do |t| t.column :name, :string t.column :number, :string end end def self.down drop_table :members end end The model is: class Member < ActiveRecord::Base validates_uniqueness_of :number end The testing fixture is: numeric_only_member: id: 1 name: John Smith number: 15171914 alpha_numeric_member: id: 2 name: Joanne Jones number: wke1234 So if I write a little test case (yes I know hard coded values are fragile): require File.dirname(__FILE__) + ''/../test_helper'' require ''member'' class ExampleTest < Test::Unit::TestCase fixtures :members def test_uniqueness_of_member dup_member = Member.new(:name => ''duplicate'', :number => ''15171914'') assert !dup_member.save assert_equal 1, dup_member.errors.count assert_equal "has already been taken", dup_member.errors.on(:number) end end Problem: "assert_equal 1, dup_member.errors.count" will fail with: test_uniqueness_of_member(SimpleTest) [test/unit/simple_test.rb:11]: <1> expected but was <2>. The following line would also fail with: test_uniqueness_of_member(SimpleTest) [test/unit/simple_test.rb:12]: <"has already been taken"> expected but was <["has already been taken", "has already been taken"]>. Solution: If I remove " require ''member'' " from the test case then everything passes. I have no idea why. (Yes I''m a newbie, please don''t laugh and point). I''m digging through ActiveRecord, UnitTest, and Ruby docs and source but haven''t found an answer yet. Any ideas? Thanks...qb --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On Sep 25, 2007, at 10:55 PM, qb wrote:> I just created a simple model and started to write unit tests for it > (I''ve cleaned out extraneous stuff). > > The migration is: > > class CreateMembers < ActiveRecord::Migration > def self.up > create_table :members do |t| > t.column :name, :string > t.column :number, :string > end > end > > def self.down > drop_table :members > end > end > > The model is: > > class Member < ActiveRecord::Base > validates_uniqueness_of :number > end > > The testing fixture is: > > numeric_only_member: > id: 1 > name: John Smith > number: 15171914You might need: number: "15171914" So that YAML keeps this a string and not an integer. You''re not using members(:numeric_only_member).number so it might not matter (the database should be a string regardless).> alpha_numeric_member: > id: 2 > name: Joanne Jones > number: wke1234 > > So if I write a little test case (yes I know hard coded values are > fragile): > > require File.dirname(__FILE__) + ''/../test_helper'' > require ''member''You shouldn''t need this as Rails will auto-load it when Member is first used.> > class ExampleTest < Test::Unit::TestCase > fixtures :members > > def test_uniqueness_of_member > dup_member = Member.new(:name => ''duplicate'', :number => > ''15171914'') > > assert !dup_member.save > assert_equal 1, dup_member.errors.count > assert_equal "has already been taken", > dup_member.errors.on(:number) > end > end > > Problem: > > "assert_equal 1, dup_member.errors.count" will fail with: > test_uniqueness_of_member(SimpleTest) [test/unit/simple_test.rb:11]: > <1> expected but was <2>. > > The following line would also fail with: > test_uniqueness_of_member(SimpleTest) [test/unit/simple_test.rb:12]: > <"has already been taken"> expected but was > <["has already been taken", "has already been taken"]>. > > Solution: > > If I remove " require ''member'' " from the test case then everything > passes. I have no idea why. (Yes I''m a newbie, please don''t laugh and > point). I''m digging through ActiveRecord, UnitTest, and Ruby docs and > source but haven''t found an answer yet. Any ideas? > > Thanks...qbI *think* that Member has already been defined when your ''require "member"'' is executed and since the idempotency of ''require'' is based on the argument (i.e., require ''foo'' and require ''./foo'' will load foo.rb from the current directory twice), the explicit require re- opens the Member class and hits the validates_uniqueness_of a second time. In addition to removing your "require ''member''", I''d also suggest writing your test like this: class ExampleTest < Test::Unit::TestCase fixtures :members def test_uniqueness_of_member dup_member = Member.new(:name => ''duplicate'', :number => members (:numeric_only_member).number) assert ! dup_member.valid? assert dup_member.errors[:number] assert_match /has already been taken/, dup_member.errors.on (:number) end end You want to know that the record isn''t valid, there''s no need to actually try to save it. You should check that the field has an error message, rather than the total error count. I tend to test for things like error message text with regexps that will allow some flexibility in the actual value. (e.g., "has already been taken. Please choose another and try again.") However, all you''re doing is testing that the validates_uniqueness_of works. Don''t you think that the Rails team already does that? You could make a case for verifying that something like a custom format is behaving correctly or that you''re using the :scope option as you expect, but unless you''re just practicing and convincing yourself how things work, I''d not normally test the things that Rails does. -Rob Rob Biedenharn http://agileconsultingllc.com Rob-xa9cJyRlE0mWcWVYNo9pwxS2lgjeYSpx@public.gmane.org --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On 9/25/07, qb <jkordyback-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> > If I remove " require ''member'' " from the test case then everything > passes. I have no idea why. (Yes I''m a newbie, please don''t laugh and > point). I''m digging through ActiveRecord, UnitTest, and Ruby docs and > source but haven''t found an answer yet. Any ideas?As Rob pointed out, it''s being caused by your model file being loaded twice, and thus the validates_uniqueness_of being run twice. You end up getting two (identical) error messages. The "second" load of your model file is actually coming from the "fixtures" line, which ends up calling: require_dependency ''member'' In order for require_dependency to do it''s magic, it has to turn your file name into an absolute path. So you get the effect of: require ''member'' require ''/some/absolute/path/to/member.rb'' Ruby doesn''t know that these are the same file, so it ends up loading the file twice, thus doubling the validates declarations. So, the short answer is: don''t "require" your models in your test cases (or use require_dependency). --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On 9/26/07, Rob Biedenharn <Rob-GBZH0y1GwQfnZcttdmLDtcI/UQi/AW5J@public.gmane.org> wrote:> However, all you''re doing is testing that the validates_uniqueness_of > works.Rob, is that *all* he''s doing? The test is too elaborate, but a case could be made that this is a regression test for the business rule that "Member numbers must be unique". It would protect him from coming along later and inadvertently removing that validation rule. I agree that we shouldn''t be testing Rails itself. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On Sep 26, 2007, at 2:44 PM, Bob Showalter wrote:> On 9/26/07, Rob Biedenharn <Rob-GBZH0y1GwQfnZcttdmLDtcI/UQi/AW5J@public.gmane.org> wrote: >> However, all you''re doing is testing that the validates_uniqueness_of >> works. > > Rob, is that *all* he''s doing? The test is too elaborate, but a case > could be made that this is a regression test for the business rule > that "Member numbers must be unique". > > It would protect him from coming along later and inadvertently > removing that validation rule. > > I agree that we shouldn''t be testing Rails itself.Stu Halloway addressed this at erubycon in Columbus,OH this summer. Blog: http://relevancellc.com/2007/7/17/posted-slides-how-not-to-test- validations Slides: http://relevancellc.com/assets/2007/7/17/KeepingTestsDry.pdf If you''re interested in a test to alert you when/if a validation is removed accidentally, then you should be devising a test for *that* (presence) and letting Rails make sure that validates_*_of does the right thing. -Rob Rob Biedenharn http://agileconsultingllc.com Rob-xa9cJyRlE0mWcWVYNo9pwxS2lgjeYSpx@public.gmane.org --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On 9/26/07, Rob Biedenharn <Rob-GBZH0y1GwQfnZcttdmLDtcI/UQi/AW5J@public.gmane.org> wrote:> > On Sep 26, 2007, at 2:44 PM, Bob Showalter wrote: > > On 9/26/07, Rob Biedenharn <Rob-GBZH0y1GwQfnZcttdmLDtcI/UQi/AW5J@public.gmane.org> wrote: > >> However, all you''re doing is testing that the validates_uniqueness_of > >> works. > > > > Rob, is that *all* he''s doing? The test is too elaborate, but a case > > could be made that this is a regression test for the business rule > > that "Member numbers must be unique". > > > > It would protect him from coming along later and inadvertently > > removing that validation rule. > > > > I agree that we shouldn''t be testing Rails itself. > > Stu Halloway addressed this at erubycon in Columbus,OH this summer. > > Blog: http://relevancellc.com/2007/7/17/posted-slides-how-not-to-test- > validations > Slides: http://relevancellc.com/assets/2007/7/17/KeepingTestsDry.pdf > > If you''re interested in a test to alert you when/if a validation is > removed accidentally, then you should be devising a test for *that* > (presence) and letting Rails make sure that validates_*_of does the > right thing.Well, that sounds good in theory. But in those slides, slide 18 looks great but the stuff on 19/20 is a mess! Devising a test for the presence of validates_uniqueness_of (instead of exercising it) is non-trivial. And I''m not sure that''s somehow "better" or "DRY''er" than just trying to create a duplicate and seeing it fail. I''m really not trying to test whether I have a validates_uniqueness_of declaration, and I''m not trying to test whether validates_uniqueness_of works in the abstract (the test doesn''t prove that anyway). Instead, I''m trying to test that my model doesn''t allow the number to be duplicated (regardless of the details of the implementation). IMHO, something like slide 17 is the correct approach, and not 18. Cheers, Bob --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---