基礎Ruby on Rails改訂新版のサンプルアプリでFakerを使ってみた

最近、Everyday Rails – RSpecによるRailsテスト入門という電子書籍を読んで、RSpecでテストコードを書くことに取り組んでいます。練習として、基礎Ruby on Rails改訂新板のサンプルアプリにRSpecでテストコードを書きました。Memberクラスは、次のようなバリデーションがあります。

class Member < ActiveRecord::Base
  include EmailAddressChecker

  attr_accessible :number, :name, :full_name, :email, :birthday, :gender, :administrator
  validates :number, presence: true,
            numericality:  { only_integer: true,
            greater_than: 0, less_than: 100, allow_blank: true },
            uniqueness: true
  validates :name, presence: true,
            format: { with: /\A&#91;A-Za-z&#93;\w*\z/, allow_blank: true,
                      message: :invalid_member_name },
            length:  { minimum:  2, maximum:  20, allow_blank: true },
            uniqueness: { case_sensitive: false }
  validates :full_name, length: { maximum:  20 }
  validate :check_email
  validates :gender, inclusion: { in: 0..1 }

  private
    def check_email
      if email.present?
        errors.add(:email, :invalid) unless well_formed_as_email_address(email)
      end
    end

    class << self
      def search(query)
        rel = order("number")
        if query.present?
          rel = rel.where("name LIKE ? OR full_name LIKE ?",
                        "%#{query}%", "%#{query}%")
        end
        rel
      end
    end
end
&#91;/ruby&#93;

FactoryGirl gemとFaker gemを使って、テストデータを生成しました。

&#91;ruby&#93;
require 'faker'

FactoryGirl.define do
  factory :member do
    sequence(:number) { |n| n unless n > 99 }
    name {
      name = Faker::Name.first_name.slice!(0, 19).capitalize
      name if name.length >= 2
    }
    full_name { Faker::Name.name.slice!(0, 19) }
    email {Faker::Internet.email }
    birthday "1981-12-01"
    gender { Faker::Number.number(1).to_i % 2 }
    administrator false

    factory :invalid_member do
      name nil
    end
  end
end

この場合、テストコードを書くと、英語環境ではテストは失敗しません。ところが、i18nで国際化して、日本語環境でテストすると、fakerは国際化に対応しているようで、nameが日本語になったり、emailが不正な表現になって失敗するようになります。バリデーションでは、nameは英字で始まり、英数字からならないとダメだからです。しかし、full_nameについては、日本語のデータが生成されるようにしたいです。fakerのサイトページを見ると、Faker::Config.locale でロケールをスイッチできるようです。そこで、次のファイルを使ってテストデータを生成するようにしました。

require 'faker'

FactoryGirl.define do
  factory :member do
    sequence(:number) { |n| n unless n > 99 }
    name {
      Faker::Config.locale = 'en-us'
      name = Faker::Name.first_name.slice!(0, 19).capitalize
      name if name.length >= 2
    }
    full_name {
      Faker::Config.locale = 'ja'
      Faker::Name.name.slice!(0, 19)
    }
    email {
      Faker::Config.locale = 'en-us'
      Faker::Internet.email
    }
    birthday "1981-12-01"
    gender { Faker::Number.number(1).to_i % 2 }
    administrator false

    factory :invalid_member do
      name nil
    end
  end
end

Faker::Config.locale でロケールをスイッチすると、その後は設定したロケールのままになると期待したのですが、そのようにはならないようで、各フィールドごとにロケールをスイッチしないとダメでした。このテストデータを使用すると、テストが通るようになりました。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です