It''s taken a little too long to see the light for unit testing, but the time has come! I realize that this isn''t the most exciting subject for most developers, but hopefully a couple of you have some sage advice. I''ve been trying out some test cases, and have focused on a single model trying to figure it all out before moving to the next one. The table / model I am working with is log_edits: id (int) employee_id (int) edit_time (datetime) edit_position (varchar 10) original_value (float 8) new_value (float 8) source_table (varchar 50) My model file log_edit.rb: class LogEdit < ActiveRecord::Base validates_presence_of :employee_id, :edit_time, :edit_position validates_presence_of :original_value, :new_value :source_table validates_numericality_of :employee_id, :original_value, :new_value end Is there a way to verify if the following is true within the model? employee_id is an integer orig_value and new_value are either whole or half numbers eg 12.0 or 3.5 and they are less then 50 but >= 0? (a reg ex for .0 or .5 might work) I''ve written up a small set of test cases to check it out, but its not working quite how I expected. Here is a snipped of what is failing. require File.dirname(__FILE__) + ''/../test_helper'' require ''test/unit'' require ''log_edit'' class LogEditTest < Test::Unit::TestCase fixtures :log_edits def test_invalid_with_empty_attributes edits_time = LogEdit.new assert !edits_time.valid? # value not set. should be invalid and therefore pass assert edits_time.errors.invalid?(:employee_id) # Set the value and it should fail since it is valid, # but no failure appears when run!! edits_time.employee_id = 123 assert edits_time.errors.invalid?(:employee_id) end end -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
> Is there a way to verify if the following is true within the model?validates_numericality_of :employee_id, :original_value, :new_value :only_integer => true> and they are less then 50 but >= 0?validates_inclusion_of :original_value, new_value :in => 0..50> orig_value and new_value are either whole or half numbers eg 12.0 or 3.5def validate # do you custom validation here end> # Set the value and it should fail since it is valid, > # but no failure appears when run!! > edits_time.employee_id = 123 > assert edits_time.errors.invalid?(:employee_id)I believe this is going to pass because you did not ask to validate the object again, so you errors has not changed from the original invalid state.> edits_time.employee_id = 123 > assert edits_time.valid? > assert edits_time.errors.invalid?(:employee_id)the last assertion here should fail because the errors has been updated by the previous line. On May 7, 4:56 pm, Bob Brazeau <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> It''s taken a little too long to see the light for unit testing, but the > time has come! I realize that this isn''t the most exciting subject for > most developers, but hopefully a couple of you have some sage advice. > > I''ve been trying out some test cases, and have focused on a single model > trying to figure it all out before moving to the next one. > > The table / model I am working with is log_edits: > id (int) > employee_id (int) > edit_time (datetime) > edit_position (varchar 10) > original_value (float 8) > new_value (float 8) > source_table (varchar 50) > > My model file log_edit.rb: > class LogEdit < ActiveRecord::Base > validates_presence_of :employee_id, :edit_time, :edit_position > validates_presence_of :original_value, :new_value :source_table > validates_numericality_of :employee_id, :original_value, :new_value > end > > Is there a way to verify if the following is true within the model? > employee_id is an integer > orig_value and new_value are either whole or half numbers eg 12.0 or 3.5 > and they are less then 50 but >= 0? > (a reg ex for .0 or .5 might work) > > I''ve written up a small set of test cases to check it out, but its not > working quite how I expected. Here is a snipped of what is failing. > > require File.dirname(__FILE__) + ''/../test_helper'' > > require ''test/unit'' > require ''log_edit'' > > class LogEditTest < Test::Unit::TestCase > fixtures :log_edits > def test_invalid_with_empty_attributes > edits_time = LogEdit.new > assert !edits_time.valid? > # value not set. should be invalid and therefore pass > assert edits_time.errors.invalid?(:employee_id) > > # Set the value and it should fail since it is valid, > # but no failure appears when run!! > edits_time.employee_id = 123 > assert edits_time.errors.invalid?(:employee_id) > end > end > > -- > Posted viahttp://www.ruby-forum.com/.--~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Thanks for the info, a lot of it makes sense. Two quick follow ups. in def validate, can I have multiple validates, ie one for the value fields, and then a second validate function for say source_table? Would it require separate validates ie def validate_value, def validate_source_table How do I call the validate within the model, or is it automatically run? Second was about the failure of the failure. So if I understand this correctly with my original code: edits_time = LogEdit.new assert !edits_time.valid? # value not set. should be invalid and therefore pass assert edits_time.errors.invalid?(:employee_id) Robert Walker wrote:> I believe this is going to pass because you did not ask to validate > the object again, so you errors has not changed from the original > invalid state. > >> edits_time.employee_id = 123 >> assert edits_time.valid? >> assert edits_time.errors.invalid?(:employee_id) > > the last assertion here should fail because the errors has been > updated by the previous line. > > On May 7, 4:56 pm, Bob Brazeau <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org>-- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
*Crud, tab + space = not my friend. Sorry for the double post. Thanks for the info, a lot of it makes sense. Two quick follow ups. in def validate, can I have multiple validates, ie one for the value fields, and then a second validate function for say source_table? Would it require separate validates ie def validate_value, def validate_source_table How do I call the validate within the model, or is it automatically run? Second was about the failure of the failure. You said that I did not ask to validate the object again. Could you explain that in more detail? How do I force an object to be validated multiple times within a single test? ie If I had a test to check all boundary conditions of 1 parameter I''d like it to evaluate it each time it is changed. Bob -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
ar_object.valid? On May 7, 2007, at 3:10 PM, Bob Brazeau wrote:> > *Crud, tab + space = not my friend. Sorry for the double post. > > Thanks for the info, a lot of it makes sense. > > Two quick follow ups. > > in def validate, can I have multiple validates, ie one for the value > fields, and then a second validate function for say source_table? > Would > it require separate validates ie def validate_value, def > validate_source_table > > How do I call the validate within the model, or is it automatically > run? > > Second was about the failure of the failure. You said that I did > not ask > to validate the object again. Could you explain that in more detail? > How do I force an object to be validated multiple times within a > single > test? ie If I had a test to check all boundary conditions of 1 > parameter I''d like it to evaluate it each time it is changed. > > Bob > > -- > Posted via http://www.ruby-forum.com/. > > >--~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Steve Ross wrote:> ar_object.valid?Dang, as simple as that huh? Added it right after the assignment and it threw the failure right where it should have. sweet! -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
> in def validate, can I have multiple validates, ie one for the value > fields, and then a second validate function for say source_table? Would > it require separate validates ie def validate_value, def > validate_source_tableAn example is worth a thousand words: class Person < ActiveRecord::Base protected def validate errors.add_on_empty %w( first_name last_name ) errors.add("phone_number", "has invalid format") unless phone_number =~ /[0-9]*/ end def validate_on_create # is only run the first time a new object is saved unless valid_discount?(membership_discount) errors.add("membership_discount", "has expired") end end def validate_on_update errors.add_to_base("No changes have occurred") if unchanged_attributes? end end> How do I call the validate within the model, or is it automatically run?Rails will take care of calling validation at the appropriate time.> Second was about the failure of the failure. You said that I did not ask > to validate the object again. Could you explain that in more detail? > How do I force an object to be validated multiple times within a single > test? ie If I had a test to check all boundary conditions of 1 > parameter I''d like it to evaluate it each time it is changed.Sorry I should have been more clear. s.ross answered this tersely, yet correctly. edits_time.valid? or assert edits_time.valid? # if you want to test the changed state On May 7, 6:10 pm, Bob Brazeau <rails-mailing-l...-ARtvInVfO7ksV2N9l4h3zg@public.gmane.org> wrote:> *Crud, tab + space = not my friend. Sorry for the double post. > > Thanks for the info, a lot of it makes sense. > > Two quick follow ups. > > in def validate, can I have multiple validates, ie one for the value > fields, and then a second validate function for say source_table? Would > it require separate validates ie def validate_value, def > validate_source_table > > How do I call the validate within the model, or is it automatically run? > > Second was about the failure of the failure. You said that I did not ask > to validate the object again. Could you explain that in more detail? > How do I force an object to be validated multiple times within a single > test? ie If I had a test to check all boundary conditions of 1 > parameter I''d like it to evaluate it each time it is changed. > > Bob > > -- > Posted viahttp://www.ruby-forum.com/.--~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Robert Walker wrote:> An example is worth a thousand words:It sure is, and it helps a lot. Was checking out the api on errors to fill in the blanks, but I didn''t see anything about the %w in there. I thought it might be a regular expression for word (only allow letters and numbers) but when I added it to the model it didn''t work. ie throw an error if it is blank, or contains bad input. [ errors.add_on_empty %w( source_table ) ] edits_time.source_table = ''`~test!@]'' # also tried ''`~!@]'' edits_time.valid? assert edits_time.errors.invalid?(:source_table) it winds up failing, meaning the ''`test!@]'' is a valid value for source table.> errors.add_on_empty %w( first_name last_name )> Rails will take care of calling validation at the appropriate time.Cool, good to know.> Sorry I should have been more clear. s.ross answered this tersely, > yet correctly.yep. I didn''t realize that .valid? caused the object to reevaluate itself, figured it would have the same problem that the invalid() call would. Now I know, and knowing if half the battle =) -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Bob Brazeau wrote:> Robert Walker wrote: >> An example is worth a thousand words: > > It sure is, and it helps a lot. Was checking out the api on errors to > fill in the blanks, but I didn''t see anything about the %w in there. I > thought it might be a regular expression for word (only allow letters > and numbers) but when I added it to the model it didn''t work. ie throw > an error if it is blank, or contains bad input. > [ errors.add_on_empty %w( source_table ) ] > > edits_time.source_table = ''`~test!@]'' # also tried ''`~!@]'' > edits_time.valid? > assert edits_time.errors.invalid?(:source_table) > > it winds up failing, meaning the ''`test!@]'' is a valid value for source > table. > >> errors.add_on_empty %w( first_name last_name ) > >> Rails will take care of calling validation at the appropriate time. > Cool, good to know. > >> Sorry I should have been more clear. s.ross answered this tersely, >> yet correctly. > > > yep. I didn''t realize that .valid? caused the object to reevaluate > itself, figured it would have the same problem that the invalid() call > would. Now I know, and knowing if half the battle =)%w is just straight-ahead ruby. It means "turn the string that follows into an array". It breaks the string up at the spaces. Just a quick and easy way to initialize an array of words. my_array = %w(four score and seven) my_array gets the value ["four", "score", "and", "seven"] jp -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
>> Bob Brazeau wrote: >> [ errors.add_on_empty %w( source_table ) ]Jeff Pritchard wrote:> %w is just straight-ahead ruby. It means "turn the string that follows > into an array". It breaks the string up at the spaces. Just a quick > and easy way to initialize an array of words. > my_array = %w(four score and seven) > my_array gets the value ["four", "score", "and", "seven"] > > jpWell that explains why it wasn''t doing anything since it was just a 1 element array. As I''ve been writing up some test cases, I was wondering what some of the best practices for Testing are - and Google has not been very helpful. I am trying to automate the writing of these tests as much as possible and have gotten it somewhat condensed, but was wondering if further improvements are possible. Right now I am testing the models, so I create a valid object in the setup function, then I test that a blank/new object is invalid, and that the object from setup is valid. Next I test each parameter''s corner cases like so - this test is for the hours in a day, in half hour increments, 0-23.5 def test_log_edit_value_corner_cases #test new_v and original_value together since they accept the same values. failure_cases = [25, 24, -1, 0.25, 23.75, ''b''] success_cases = [0, 0.5, 1, 17, 17.5, 23, 23.5] #start with a valid object, then just test that #it is (in)valid by changing just these fields failure_cases.each do |f_case| @valid_obj.new_value = f_case @valid_obj.original_value = f_case @valid_obj.valid? assert @valid_obj.errors.invalid?(:new_value) assert @valid_obj.errors.invalid?(:original_value) assert !@valid_obj.valid? end #Don''t test the fields specifically. #If anything is bad, the whole thing will be. success_cases.each do |s_case| @valid_obj.new_value = s_case @valid_obj.original_value = s_case assert @valid_obj.valid? end end Here you can see that all I have to do is add new values to the array to change my cases. pretty simple. But each and every attribute will have these same two loops/function, with just the attributes and the values of these arrays changed. I was wondering if you can have non test functions within a test file, and if they be called and have stuff returned, or if I could create some sort of generic function in a seperate file and have the test files include it. Just because something may be possible, it doesn''t mean its a good idea. I didn''t know if either way was generally accepted and was wondering what others thought. Thanks for any advice. -- Posted via http://www.ruby-forum.com/. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---