最近、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[A-Za-z]\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 [/ruby] FactoryGirl gemとFaker gemを使って、テストデータを生成しました。 [ruby] 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 でロケールをスイッチすると、その後は設定したロケールのままになると期待したのですが、そのようにはならないようで、各フィールドごとにロケールをスイッチしないとダメでした。このテストデータを使用すると、テストが通るようになりました。