私はRailsでTDDから旅を始めましたが、解決策が見つからないモデル検証のテストに関する小さな問題に遭遇しました。ユーザーモデルがあるとします。
class User < ActiveRecord::Base
validates :username, :presence => true
end
そして簡単なテスト
it "should require a username" do
User.new(:username => "").should_not be_valid
end
これはプレゼンス検証を正しくテストしますが、より具体的にしたい場合はどうすればよいですか?たとえば、エラーオブジェクトでfull_messagesをテストします。
it "should require a username" do
user = User.create(:username => "")
user.errors[:username].should ~= /can't be blank/
end
最初の試み(should_not be_validを使用)に関する私の懸念は、RSpecが説明的なエラーメッセージを生成しないことです。それは単に「有効であると思われますか?ただし、2番目のテスト例には小さな欠点があります。エラーオブジェクトを取得するために、新しいメソッドの代わりにcreateメソッドを使用します。
私は自分のテストでテスト対象をより具体的にしたいのですが、同時にデータベースに触れる必要はありません。
誰にも入力がありますか?
最初に、あなたは邪悪な名前を持っていると言いたいです。
第二に、RORを使用してTDDに取り組んでいるおめでとうございます。
最も簡単で迅速な解決策は、次のような各テストの前に新しい有効なモデルを生成することです。
before(:each) do
@user = User.new
@user.username = "a valid username"
end
しかし、私が提案するのは、有効なモデルを自動的に生成するすべてのモデルのファクトリーを設定し、個々の属性を調整して検証を確認することです。このために FactoryGirl を使用したい:
基本的に、設定するとテストは次のようになります。
it "should have valid factory" do
FactoryGirl.build(:user).should be_valid
end
it "should require a username" do
FactoryGirl.build(:user, :username => "").should_not be_valid
end
ああ、これは 良いrailscast です。
幸運を :)
更新: バージョン3. の時点で、ファクトリーガールの構文が変更されました。これを反映するためにサンプルコードを修正しました。
モデル検証(およびより多くのアクティブレコード)をテストする簡単な方法は、 shoulda または remarkable のようなgemを使用することです。
次のようにテストを許可します。
describe User
it { should validate_presence_of :name }
end
これを試して:
it "should require a username" do
user = User.create(:username => "")
user.valid?
user.errors.should have_key(:username)
end
新しいバージョンのrspecでは、代わりにexpectを使用する必要があります。そうしないと、警告が表示されます。
it "should have valid factory" do
expect(FactoryGirl.build(:user)).to be_valid
end
it "should require a username" do
expect(FactoryGirl.build(:user, :username => "")).not_to be_valid
end
従来、機能またはリクエストの仕様でエラーコンテンツの仕様を処理していました。したがって、たとえば、以下に要約する類似の仕様があります。
機能仕様例
before(:each) { visit_order_path }
scenario 'with invalid (empty) description' , :js => :true do
add_empty_task #this line is defined in my spec_helper
expect(page).to have_content("can't be blank")
そのため、何かが有効かどうかをテストするモデル仕様がありますが、エラーメッセージの正確な出力をテストする機能仕様があります。参考までに、これらの機能仕様には here で見つかるCapybaraが必要です。
@nathanvdaが言ったように、Thoughtbotの Shoulda Matchers gemを利用します。ロッキングを使用すると、プレゼンスとカスタムエラーメッセージをテストするために、次の方法でテストを作成できます。
RSpec.describe User do
describe 'User validations' do
let(:message) { "I pitty da foo who dont enter a name" }
it 'validates presence and message' do
is_expected.to validate_presence_of(:name).
with_message message
end
# shorthand syntax:
it { is_expected.to validate_presence_of(:name).with_message message }
end
end
ここでのパーティーに少し遅れましたが、shouldaマッチャーを追加したくない場合、これはrspec-Railsとfactorybotで動作するはずです。
# ./spec/factories/user.rb
FactoryBot.define do
factory :user do
sequence(:username) { |n| "user_#{n}" }
end
end
# ./spec/models/user_spec.rb
describe User, type: :model do
context 'without a username' do
let(:user) { create :user, username: nil }
it "should NOT be valid with a username error" do
expect(user).not_to be_valid
expect(user.errors).to have_key(:username)
end
end
end