# ============================================================================= # Purpose: Refactored TestCase for simple Rails ActiveRecord::Base and # ActiveForm classes. # Author: Manuel Holtgrewe <purestorm at ggnore dot net> # License: Public Domain # # Feel free to flesh out the tests further and make it a more poweful library. # Drop me a line if you find the module useful or if you created something more # powerful on top of it. # ============================================================================= # # Include this module in your test classes. Then, you define some valid data, # the model class to test and some "patches" to the valid data to make it invalid. # # Sure, this will only work for very simple models but you want to spend as few # time on those as possible, right? # # Assuming you have the following model: # # class MyModel < ActiveRecord::Base # validates_length_of :title, :in => 10..100 # validates_numericality_of :number # end # # You can then write the following TestCase: # # class MyModelTest < Test::Unit::TestCase # include SimpleMethodTests # The basic tests are defined in this module. # # fixtures :my_models # # def setup # @model_class = MyModel # @valid_data = { :title => 'Abracabra!', :number => 10 } # @invalid_patches = # [ # [ :title, nil ], [ :title, 'a' * 9 ], [ :title, 'a' * 101 ], # [ :number, nil ], [ :number, 'a' ], [ :title, '123a' ], # ] # end # # def test_a_nonbasic_test # flunk, "Wheee!" # end # # # Overwrite a test from the mixin. # def test_valid_should_return_false_and_add_errors_with_invalid_data # assert true, "Removing this test!" # end # end # # You can both test ActiveRecord::Base and ActiveForm classes (CRUD is not tested # on ActiveForm classes). If you test ActiveRecord::Base classes then you have to # provide at least one fixture. module SimpleModelTests def test_valid_should_return_true_with_valid_data # Do not use Model.new(attributes) since some might be marked as protected. model = @model_class.new @valid_data.each { |key, value| model.send("#{key}=".to_sym, value) } assert model.valid? assert_equal 0, model.errors.count end def test_valid_should_return_false_and_add_errors_with_invalid_data @invalid_patches.each do |key, value| invalid_data = @valid_data.dup invalid_data[key] = value # Do not use Model.new(attributes) since some might be marked as protected. model = @model_class.new invalid_data.each { |invalid_key, invalid_value| model.send("#{invalid_key}=".to_sym, invalid_value) } assert !model.valid?, "invalid_data[#{key.inspect}] == #{value.inspect}, errors: #{model.errors.full_messages.join('; ')}" # If the property we set was a foreign key named NAME_id then the error # gets added to the property NAME of the object if the object is an # ActiveRecord::Base object. if key.to_s =~ /^(.*)_id$/ and model.respond_to?($1.to_sym) then assert_not_nil model.errors.on($1.to_sym), "invalid_data[#{$1.to_sym.inspect}] == #{value.inspect}" else assert_not_nil model.errors.on(key), "invalid_data[#{key.inspect}] == #{value.inspect}" end end end def test_create_should_work_correctly # We only want to test this if we test an ActiveRecord::Base class. return if not @model_class.new.respond_to?(:save) old_count = @model_class.count # Do not use Model.new(attributes) since some might be marked as protected. model = @model_class.new @valid_data.each { |key, value| model.send("#{key}=".to_sym, value) } assert model.save, "errors: #{model.errors.full_messages.join('; ')}" assert model.reload assert_equal old_count+1, @model_class.count end def test_update_should_work_correctly # We only want to test update if the model objects have a method "save". return if not @model_class.new.respond_to?(:update) # We assume that there is at least one valid record in the database with # different data than the @valid_data you specified above. # # We order by id to make the result predictable. model = @model_class.find(:first, :order => 'id ASC') @valid_data.each { |key, value| model.send("#{key}=".to_sym, value) } assert model.save, "errors: #{model.errors.full_messages.join('; ')}" assert model.reload @valid_data.each do |key, value| case value when Float then assert_in_delta value, model.send(key), 0.01 else assert_equal value, model.send(key) end end end def test_destroy_should_work_correctly # We only want to test this if we test an ActiveRecord::Base class. return if not @model_class.new.respond_to?(:destroy) old_count = @model_class.count model = @model_class.find(:first) id = model.id model.destroy assert_raises(ActiveRecord::RecordNotFound) { @model_class.find(id) } assert_equal old_count-1, @model_class.count end end
You need to create an account or log in to post comments to this site.