# RSpec (Adding Data to Test) ### Fixtures 運作方式:使用YAML檔將資料直接塞入資料庫中,並轉換成ActiveRecord物件。(可以快速建構全域資料) 1. 資料庫中必須有相對應的欄位 2. 並不受ActiveRecord的驗證影響 3. Fixture會在測試一開始建立完成,測試完後會將過程rolled back ##### 優點 1. 運行速度快 2. 假資料會一直存在 ##### 缺點 1. Fixture資料是全域的 2. 關聯性需要自己建立 3. 無法立即了解資料建立步驟 4. Fixture資料是脆弱的 --- ### Factories 運作方式: 1. build(:project):回傳model instance,但並不會存進資料庫中 2. create(:project):回傳model instance,會存進資料庫中 3. attributes_for(:project):回傳物件屬性的hash值 4. build_stubbed(:project):很像build,但會給一個假的ActiveRecord ID 方法: *_pair:使用factory建立出兩個物件 ex: create_pair(:project) *_list:使用factory建立出多個物件 ex: create_list(:project, 5) ##### Inherited Factories ```ruby= FactoryBot.define do factory :task do sequence(:title) {|n| "Task #{n}"} end factory :big_task, parent: :task do size 5 end factory :small_task, parent: :task do size 1 end end ``` ```ruby= FactoryBot.define do factory :task do sequence(:title) {|n| "Task #{n}"} size 3 completed_at nil end trait :small do size 1 end trait :large do size 5 end end ``` ##### Dates and Times ```ruby= let(:runway){create(:proect, name: "Project Runway", start_date: "2018-01-20")} let(:greenlight){create(:proect, name: "Project Greenlight", start_date: "2018-02-24")} let(:gutenberg){create(:proect, name: "Project Gutenberg", start_date: "2018-01-31")} it "finds recently started projects" do actual = Project.find_recently_started(6.months) expect(actual.size).to eq(3) end ``` 六個月後測試就過不了 解決方法: 1. Relative Dates ```ruby= let(:runway){create(:proect, name: "Project Runway", start_date: 1.week.ago)} let(:greenlight){create(:proect, name: "Project Greenlight", start_date: 1.month.ago)} let(:gutenberg){create(:proect, name: "Project Gutenberg", start_date: 1.day.ago)} it "finds recently started projects" do actual = Project.find_recently_started(6.months) expect(actual.size).to eq(3) end ``` 2. Stubbing time ActiveSupport::Testing::TimeHelpers#travel ActiveSupport::Testing::TimeHelpers#travel_to ```ruby= #travel_to it "finds recently started projects" do travel_to(Date.parse("2018-02-10")) actual = Project.find_recently_started(6.months) expect(actual.size).to eq(3) end ``` ```ruby= #travel it "knows if the project is over" do p = Project.new(:start_date => Date.today, :end_date = Date.today + 8.weeks) expect(p).not_to be_complete teavel(10.weeks) expect(p).to be_complete end ```