テスト用インスタンス生成ヘルパー

ふと思った

テストの際に、invalidなインスタンスを作成したり、検索テスト用に、対象カラムだけの値を変えたようなインスタンス/レコードを作成することが多い。
その際に、全てのカラムを指定するのが面倒だったりする。特に、validate_presence_ofとかの検証をかけていると、その部分のカラムも指定してやらないとcreateできない。そこで、こんなヘルパーを作ってみた。

  • test_helper.rb
  def create_new_record(klass,default,options = {},*nil_on_new_record)
    if options.keys.include?(:all)
      attrs = klass.column_names.inject({}){|h,k| h.merge(k => options[:all])}
    else
      nil_on_new_record = nil_on_new_record | [:id, :created_at, :updated_at]
      attrs = default.attributes.reject{|k,v| nil_on_new_record.include?(k.to_sym)}
      attrs.merge!(options)
    end

    klass.new(attrs)
  end


呼び出し側はこんな感じ。

class UserTest < Test::Units::TestCase
  fixtures :users

  def test_validates_presence_of
    user = new_record(:all => nil)
    assert !user.valid?
    assert user.errors.invalid?(:name)
    assert user.errors.invalid?(:address)
  end
  
  def test_validates_length_of
    too_long_name = "abcdeabcdeabcdeabcdea"  #maximum => 20
    user = new_record(:name => too_long_name)
    assert !user.valid?
    assert user.errors.invalid?(:name)
  end

  private

  def new_record(options = {})
    create_new_record(User,@bob,options)
  end
end
  • users.yml
bob:
  id: 1
  name: bob
  address: bob@address.com
  created_at: <%= 2.day.ago.to_formatted_s(:db)%> 
  updated_at: <%= 1.day.ago.to_formatted_s(:db)%> 


このnew_recordメソッドを各テスト用のクラスに実装する。(冗長かな?)

  • create_new_record:対象のクラス
  • default:土台レコード。fixtureのデータを渡すとよい。optionsでこの値の一部を変更してインスタンスを生成する
  • options:上書きする値を指定。:allを指定すると、全てのカラムがその値のインスタンスができる。(専ら:all => nilで使用)
  • nil_on_new_record::new_record => trueのインスタンスでは値が入らない。idは典型。fixtureではidとかが入ってしまっているのでそれを排除する。


インスタンスを生成するのに関数型っぽいのがなんかな・・・