FactoryGirl の記述
モデルを作成した時点で FactoryGirl の雛形は自動に作成してくれる。今回は、テストのために属性値だけ修正しておく。
FactoryGirl.define do factory :year do year 2014 default_year true end end
昨日、spec/factories を監視するように設定したため、保存すると自動的にテストが作動する。
17:23:33 - INFO - Running: spec/models/year_spec.rb No examples found. Finished in 0.00028 seconds (files took 1.85 seconds to load) 0 examples, 0 failures
まだテストは書いていないので、何も起こらない。
モデルのテスト記述
RSpec では let という遅延評価と保持の仕組みがある。以下のように定義する。
RSpec.describe Year, :type => :model do let(:year) { FactoryGirl.build(:year) } end
このようにすると year と記述すると FactoryGirl.build(:year) が実行される。同じテスト内では、その値が保持されるので FactoryGirl.build は発火しない。Ruby で真面目に書くとこんな感じになる。
def year; @year ||= FactoryGirl.build(:year); end
余計なインスタンス変数ができない分、let の方がわかりやすい。
RSpec のブロック内に一つテストを追加してみる。FactoryGirl で year が生成できるかどうかをテストするものである。
it { expect(year).to be_valid }
保存すると、Guard が作動する。これは問題ないためテストは通過する。
Year should be valid Finished in 0.01289 seconds (files took 1.69 seconds to load) 1 example, 0 failures
it の第一引数を省略すると、テスト内容から自動的に仕様文書を作成してくれる。なるべく楽をするように、これからは it の引数を省略できるようなテストを記述したい。
テストを追加
year と default_year 属性は nil 禁止なので、属性が nil の時に有効でないことを確認する。
[ :year, :default_year ].each do |key| context "when #{key} is nil" do it { expect(FactoryGirl.build(:year, key => nil)).to_not be_valid } end end
結果は以下のようになる。
18:21:16 - INFO - Running: spec/models/year_spec.rb Year should be valid when year is nil should not be valid (FAILED - 1) when default_year is nil should not be valid (FAILED - 2) Failures: 1) Year when year is nil should not be valid Failure/Error: it { expect(FactoryGirl.build(:year, key => nil)).to_not be_valid } expected #<Year id: nil, year: nil, default_year: true, created_at: nil, updated_at: nil> not to be valid # ./spec/models/year_spec.rb:9:in `block (4 levels) in <top (required)>' 2) Year when default_year is nil should not be valid Failure/Error: it { expect(FactoryGirl.build(:year, key => nil)).to_not be_valid } expected #<Year id: nil, year: 2014, default_year: nil, created_at: nil, updated_at: nil> not to be valid # ./spec/models/year_spec.rb:9:in `block (4 levels) in <top (required)>' Finished in 0.01561 seconds (files took 1.82 seconds to load) 3 examples, 2 failures Failed examples: rspec ./spec/models/year_spec.rb:9 # Year when year is nil should not be valid rspec ./spec/models/year_spec.rb:9 # Year when default_year is nil should not be valid
実装を記述していないので、当然エラーとなる。
app/models/year.rb に validation を追加する(default_year は boolean なので presence ではテストできないのを忘れていたので後日修正)。
class Year < ActiveRecord::Base validates :year, presence:true validates :default_year, inclusion: { in: [true, false] } end
この結果、テストが無事に通過する。
18:57:27 - INFO - Running: spec/models/year_spec.rb Year should be valid when year is nil should not be valid when default_year is nil should not be valid Finished in 0.30622 seconds (files took 1.86 seconds to load) 3 examples, 0 failures
同様に unique 性のテストをする。
context "when duplicate year" do it { year.save; expect(FactoryGirl.build(:year)).to_not be_valid } end
この結果エラーとなることが確認できる。
19:12:20 - INFO - Running: spec/models/year_spec.rb Year should be valid when year is nil should not be valid when default_year is nil should not be valid when duplicate year should not be valid (FAILED - 1) Failures: 1) Year when duplicate year should not be valid Failure/Error: it { year.save; expect(FactoryGirl.build(:year)).to_not be_valid } expected #<Year id: nil, year: 2014, default_year: true, created_at: nil, updated_at: nil> not to be valid # ./spec/models/year_spec.rb:15:in `block (3 levels) in <top (required)>' Finished in 0.30945 seconds (files took 1.65 seconds to load) 4 examples, 1 failure Failed examples: rspec ./spec/models/year_spec.rb:15 # Year when duplicate year should not be valid
このテストを通過させるために、uniqueness の validation を追加する。
validates :year, presence:true, uniqueness:true
この結果、テストが無事通過する。
19:12:51 - INFO - Running: spec/models/year_spec.rb Year should be valid when year is nil should not be valid when default_year is nil should not be valid when duplicate year should not be valid Finished in 0.29406 seconds (files took 1.62 seconds to load) 4 examples, 0 failures
今日はここまで。
written by iHatenaSync