Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

http://ttt.ggnore.net

« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS 

Refactoring of simple Model test for Rails

   1  
   2  # =============================================================================
   3  # Purpose: Refactored TestCase for simple Rails ActiveRecord::Base and 
   4  #          ActiveForm classes.
   5  # Author:  Manuel Holtgrewe <purestorm at ggnore dot net>
   6  # License: Public Domain
   7  #
   8  # Feel free to flesh out the tests further and make it a more poweful library.
   9  # Drop me a line if you find the module useful or if you created something more
  10  # powerful on top of it.
  11  # =============================================================================
  12  #
  13  # Include this module in your test classes. Then, you define some valid data,
  14  # the model class to test and some "patches" to the valid data to make it invalid.
  15  #
  16  # Sure, this will only work for very simple models but you want to spend as few
  17  # time on those as possible, right?
  18  #
  19  # Assuming you have the following model:
  20  #
  21  #   class MyModel < ActiveRecord::Base
  22  #     validates_length_of :title, :in => 10..100
  23  #     validates_numericality_of :number
  24  #   end
  25  #
  26  # You can then write the following TestCase:
  27  #
  28  #  class MyModelTest < Test::Unit::TestCase
  29  #    include SimpleMethodTests # The basic tests are defined in this module.
  30  #
  31  #    fixtures :my_models
  32  #
  33  #    def setup
  34  #      @model_class = MyModel
  35  #      @valid_data = { :title => 'Abracabra!', :number => 10 }
  36  #      @invalid_patches =
  37  #        [
  38  #          [ :title, nil ], [ :title, 'a' * 9 ], [ :title, 'a' * 101 ],
  39  #          [ :number, nil ], [ :number, 'a' ], [ :title, '123a' ],
  40  #        ]
  41  #    end
  42  #
  43  #    def test_a_nonbasic_test
  44  #      flunk, "Wheee!"
  45  #    end
  46  #
  47  #    # Overwrite a test from the mixin.
  48  #    def test_valid_should_return_false_and_add_errors_with_invalid_data
  49  #      assert true, "Removing this test!"
  50  #    end
  51  #  end
  52  #
  53  # You can both test ActiveRecord::Base and ActiveForm classes (CRUD is not tested
  54  # on ActiveForm classes). If you test ActiveRecord::Base classes then you have to
  55  # provide at least one fixture.
  56  module SimpleModelTests
  57    def test_valid_should_return_true_with_valid_data
  58      # Do not use Model.new(attributes) since some might be marked as protected.
  59      model = @model_class.new
  60      @valid_data.each { |key, value| model.send("#{key}=".to_sym, value) }
  61  
  62      assert model.valid?
  63      assert_equal 0, model.errors.count
  64    end
  65    
  66    def test_valid_should_return_false_and_add_errors_with_invalid_data
  67      @invalid_patches.each do |key, value|
  68        invalid_data = @valid_data.dup
  69        invalid_data[key] = value
  70      
  71        # Do not use Model.new(attributes) since some might be marked as protected.
  72        model = @model_class.new
  73        invalid_data.each { |invalid_key, invalid_value| model.send("#{invalid_key}=".to_sym, invalid_value) }
  74  
  75        assert !model.valid?, "invalid_data[#{key.inspect}] == #{value.inspect}, errors: #{model.errors.full_messages.join('; ')}"
  76        
  77        # If the property we set was a foreign key named NAME_id then the error 
  78        # gets added to the property NAME of the object if the object is an
  79        # ActiveRecord::Base object.
  80        if key.to_s =~ /^(.*)_id$/ and model.respond_to?($1.to_sym) then
  81          assert_not_nil model.errors.on($1.to_sym), "invalid_data[#{$1.to_sym.inspect}] == #{value.inspect}"
  82        else
  83          assert_not_nil model.errors.on(key), "invalid_data[#{key.inspect}] == #{value.inspect}"
  84        end
  85      end
  86    end
  87    
  88    def test_create_should_work_correctly
  89      # We only want to test this if we test an ActiveRecord::Base class.
  90      return if not @model_class.new.respond_to?(:save)
  91      
  92      old_count = @model_class.count
  93      
  94      # Do not use Model.new(attributes) since some might be marked as protected.
  95      model = @model_class.new
  96      @valid_data.each { |key, value| model.send("#{key}=".to_sym, value) }
  97      
  98      assert model.save, "errors: #{model.errors.full_messages.join('; ')}"
  99      assert model.reload
 100      
 101      assert_equal old_count+1, @model_class.count
 102    end
 103    
 104    def test_update_should_work_correctly
 105      # We only want to test update if the model objects have a method "save".
 106      return if not @model_class.new.respond_to?(:update)
 107      
 108      # We assume that there is at least one valid record in the database with
 109      # different data than the @valid_data you specified above.
 110      #
 111      # We order by id to make the result predictable.
 112      model = @model_class.find(:first, :order => 'id ASC')
 113      
 114      @valid_data.each { |key, value| model.send("#{key}=".to_sym, value) }
 115    
 116      assert model.save, "errors: #{model.errors.full_messages.join('; ')}"
 117      assert model.reload
 118      
 119      @valid_data.each do |key, value|
 120        case value
 121        when Float then
 122          assert_in_delta value, model.send(key), 0.01
 123        else
 124          assert_equal value, model.send(key)
 125        end
 126      end
 127    end
 128    
 129    def test_destroy_should_work_correctly
 130      # We only want to test this if we test an ActiveRecord::Base class.
 131      return if not @model_class.new.respond_to?(:destroy)
 132      
 133      old_count = @model_class.count
 134      
 135      model = @model_class.find(:first)
 136      
 137      id = model.id
 138      
 139      model.destroy
 140      
 141      assert_raises(ActiveRecord::RecordNotFound) { @model_class.find(id) }
 142      
 143      assert_equal old_count-1, @model_class.count
 144    end
 145  end
« Newer Snippets
Older Snippets »
Showing 1-1 of 1 total  RSS