1. 程式人生 > >Rails 5 Test Prescriptions 第6章Adding Data to Tests

Rails 5 Test Prescriptions 第6章Adding Data to Tests

vertical ransac top 速度 第6章 sat 方便 remove 必須

bcreate the data quickly and easily。考慮測試運行的速度。

fixtures and factories.以及下章討論的test doubles,還有原生的create創建的,沒有一個方案可以解決所有情景。


Fxitures

如果想使用固件。RSpec目錄是spec/fixtures/projects.yml。 Mini test的目錄是test/fixtures/

runway:
name: Project Runway

due_date: 2016-12-18

projects(:runway)

名字可以描述用途,比如projects(:project_with_no_due_date)

Fixture接受ERB files.可以使用<%= %> ,不建議使用使用循環。

Loading Fixture Data

在測試開始時固件會一次性加載,使用事物transaction,因此在測試結束時會回滾。回歸初始狀態。

固件運行速度塊。固件是全局性的數據 儲存在database中。

固件是分散的,不適合管理connections,關聯數據。

總之,固件不適合在復雜的程序使用。


Factories factory_bot

gem ‘factory_bot_rails‘ 目錄spec/factories/

在spec的一個文件中配置:

RSpec.configure do |config|
config.include FactoryBot::Syntax::Methodsend

每次用create方法無需加上FactoryBot前綴了。

詳細用法:本博客: https://www.cnblogs.com/chentianwei/p/9047596.html

Factory_bot假定class的名字就是你定義的名字。如果要自定義類,需要指定類名。

FactoryBot.define do factory :project, class: Project do name "Project Runway" due_date {Date.today - rand(50)} #隨機時間。50天內的。
endend

Basic Factory Creation

build(:project): 非關聯對象可以使用。

create(:project):別用,除非對象之間有關聯,必須存入數據庫。因為會讓測試減慢。

attributes_for(:project) 需要對hash屬性進行驗證時,使用,一般見於controller test。


build_stubbed(:project) Unlike build, it assigns a fake ActiveRecord ID to the model and stubs out database-interaction methods (like save) such that the test raises an exception if they are called.

Prescription: 盡量使用這個方法,有build的一切功能,還能生成一個假Rails id,有了這個就能建立belongs_to 關聯,同時不會被存入數據庫。

*_pair and *_list 兩個方法,沒看。

Associations and Factories

FactoryBot.define do factory :task do title "Thing to do" size 1 completed_at nil project

#這樣調用task = create(:task)就會自動調用task.project = create(:project)

endend

也可以單獨建立關聯:

task = FactoryBot.create(:task, project: Project.new)

如果已經在factory definition中建立了關聯,同時不想在測試中有value,設置nil

task = FactoryBot.create(:task, project: nil).

如果關聯名字不匹配factory name或者你想指定關聯對象的默認的屬性:

在factory definition 中使用association方法

association :doer, factory: :user, name: "Task Doer"

只有保存在數據庫中,對象有了id才能關聯。但可以使用build_stubbed來創建不保存的對象

或者使用create方法。

作者建議在定義中建立關聯,但不設置屬性。屬性在測試中設置。

association :user

更直接的 user

Managing Duplication in Factories

對於2個以上的factories, Factory_bot可以做到管理。文檔裏面有許多技巧,但以下3個最常用。

sequence方法

對於需要unique values 的屬性,如登陸,或電子郵件。可以使用sequence方法。

sequence(:title) { |n| "Task #{n}"}

起始n是1. 每被調用一次n加1。

inherited factories 繼承的特性

FactoryBot.define do factory :task do sequence(:title){ |n| "Task #{n}"} #可以嵌套進來 factory :big_task do size 5 end factory :small_task do size 1 end end#或者加上parent: :task factory :middle_task, parent: :task do size 3 endend

trait方法

trait

優點:設置一個有意義的名字,方便理解

缺點:需要額外的輸入和增加了復雜度。

用於指定一批的特定的屬性,一個省事的方法。

這個方法放在factory :task的塊中,就可以被task使用。

FactoryBot.define do

factory :task do title "Thing to do" size 1 completed_at nil trait :small do size 1 end

#繼承一個對象,並使用了trait

factory :trivial do small end endend

調用: let(:task){build(:task, :smal)}

Preventing Factory Abuse

創建最小數量的數據剛好夠測試用就可以了。


Dates and Times

測試歷法邏輯,讓人頭疼,但可以使用a couple of things 來簡化時間邏輯這個野獸 .

Using Relative Dates

Date.today 和 1.day.ago, 2.months.ago, 2.weeks.ago結合使用。

如在

factory :project do

start_date {1.week.ago}

end


gutenberg:

start_date: <%= 1.day.ago %>

缺點就是如果某個時間是已知的,就沒辦法使用相對時間了。

Stubbing Time

把時間凍結!!!用a stub來明確指定時間。

需要用到Raisl helper方法。

ActiveSupport::Testing::TimeHelpers#travel

Changes current time to the time in the future or in the past by a given time difference by stubbing Time.now, Date.today, and DateTime.now. The stubs are automatically removed at the end of the test.

travel(duration, &block)
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
travel 1.day do
  User.create.created_at # => Sun, 10 Nov 2013 15:34:49 EST -05:00
end
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00

如 travel 1.month, 接受一段時間作為參數。 一個整數。

ActiveSupport::Testing::TimeHelpers#travel_to

travel_to(date_or_time)

接受1個固定的時間/日記,作為參數。

pasting

Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00
travel_to Time.zone.local(2004, 11, 24, 01, 04, 44) do
  Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00
end
Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00

trave_back 重置時間回到初始狀態。

可以在這兩個參數的塊內,進行斷言,或者期望expect.

Comparing Time

Ruby有三個獨立的時間類。Time, Date, DateTime.

因此Date的實例和DateTime的實例是無法比較和加減的

使用to_s(:db)進行轉化。

1.day.ago.to_date.to_s(:db) => "2018-05-25" 1.day.ago.to_date => Fri, 25 May 2018

Setting Rails Timestamps

可以使用created_at 在預制件,或者固件中

Rails 5 Test Prescriptions 第6章Adding Data to Tests