固件:Rails 默認(rèn)提供了快速生成示例數(shù)據(jù)的工具,叫做“固件”墨吓。
固件是一個(gè)yaml格式的文件范删,可以用來(lái)生成示例數(shù)據(jù)。
例如下面是一個(gè)Contact
model的固件:
# contact.yml
aaron:
firstname: "Aaron"
lastname: "Sumner"
email: "aaron@everydayrails.com"
john:
firstname: "John"
lastname: "Doe"
email: "johndoe@nobody.org"
在測(cè)試中恃锉,我們使用contact(:aaron),就會(huì)得到一個(gè)聯(lián)系人隔盛。
固件有兩個(gè)問(wèn)題我是極力避免的:
- 固件中的數(shù)據(jù)很容易被破壞(這意味著要花費(fèi)與編寫測(cè)試和應(yīng)用代碼相等的時(shí)間維護(hù)測(cè)試數(shù)據(jù));
- Rails 在把固件中的數(shù)據(jù)存入“測(cè)試數(shù)據(jù)庫(kù)”時(shí)會(huì)跳過(guò) Active Record層。這意味著很多重要的操作,例如模型的數(shù)據(jù)驗(yàn)證,會(huì)被忽略朗儒。這樣可不好颊乘。
預(yù)構(gòu)件:簡(jiǎn)單靈活地創(chuàng)建測(cè)試數(shù)據(jù)。Factory Girl
這個(gè)工具不像固件那么容易破壞,方便使用,生成的測(cè)試數(shù)據(jù)也很可靠醉锄。
缺點(diǎn)
- 會(huì)降低測(cè)試速度
在應(yīng)用中使用預(yù)構(gòu)件
在spec文件夾下創(chuàng)建factories/contacts.rb
并寫入下面的代碼
FactoryGirl.define do
factory :contact do
firstname "John"
lastname "Doe"
sequence(:email) { |n| "johndoe#{n}@example.com"}
end
end
** sequence是FactoryGirl
提供的一個(gè)功能乏悄,每調(diào)用一次,n的值都會(huì)+1**
*** 只要模型中有唯一性驗(yàn)證恳不,都可以使用sequence(序列)***
測(cè)試代碼:
require 'rails_helper'
describe Contact do
it 'has a valid build' do
expect(FactoryGirl.build(:contact)).to be_valid
end
it 'is invalid without a firstname' do
contact = FactoryGirl.build(:contact, firstname: nil) contact.valid?
expect(contact.errors[:firstname]).to include("can't be blank")
end
it 'is invalid with a duplicate email address' do
FactoryGirl.create(:contact, email: 'fgcui@outlook.com')
contact = FactoryGirl.build(:contact,email:'fgcui@outlook.com')
contact.valid?
expect(contact.errors[:email]).to include("has already been taken")
end
end
*** FactoryGirl.build 的 作 用 是 在 內(nèi) 存 中 存 儲(chǔ) 一 個(gè) 新 測(cè) 試 對(duì) 象;FactoryGirl.create 的作用是把對(duì)象永久存儲(chǔ)到應(yīng)用的測(cè)試數(shù)據(jù)庫(kù)中檩小。***
生成更真實(shí)的虛擬數(shù)據(jù)-Faker
這里我們介紹一個(gè)虛擬數(shù)據(jù)生成工具Faker.
使用Faker之后我們的factories
的代碼就變成了下面的樣紙。它會(huì)生成看起來(lái)更真實(shí)的測(cè)試數(shù)據(jù)
FactoryGirl.define do
factory :contact do
firstname { Faker::Name.first_name }
lastname { Faker::Name.last_name }
email { Faker::Internet.email }
end
end