Kikyo

使用fabrication生成测试用数据

rails默认用fixture创建测试数据,但是fixture直接操作数据库,不能利用ActiveRecord,要创造复杂的数据时就会非常痛苦。 因此出现了fabrication, factory_giri 等,在这两者中我最终选择了fabrication,因为它更加灵活,更加优美。

https://github.com/paulelliott/fabrication

数据模型

class Company < ApplicationRecord
  has_many :stocks
  has_many :staffs
  has_many :users, through: :staffs
end
class User < ApplicationRecord
end
class Product < ApplicationRecord
  belongs_to :stock
end
class Staff < ApplicationRecord
  belongs_to :user
  belongs_to :company
end
class Stock < ApplicationRecord
  belongs_to :product
  belongs_to :company
end

创建数据

初步

# 定义 company Fabricator
Fabricator(:company) do
  name { SecureRandom.hex(5) }
  contacts { SecureRandom.hex(3) }
  phone '1111111'
end
irb(main):012:0> Fabricate(:company)
=> #<Company id: 980193688, name: "d153c213e4", contacts: "995add", phone: "1111111", created_at: "2016-04-29 01:40:26", updated_at: "2016-04-29 01:40:26">

这很简单,不值得一提对吧!

关联关系

Fabricator(:product) do
  name { SecureRandom.hex(5) }
end
# 定义 stock Fabricator
Fabricator(:stock) do
  product
  company
end
irb(main):007:0> Fabricate(:stock)
  ...
  SQL (0.3ms)  INSERT INTO `products` (`name`, `created_at`, `updated_at`) VALUES ('44434bee4c', '2016-04-29 01:42:39', '2016-04-29 01:42:39')
  SQL (0.2ms)  INSERT INTO `companies` (`name`, `contacts`, `phone`, `created_at`, `updated_at`) VALUES ('01382eb7e5', '8569b3', '1111111', '2016-04-29 01:42:39', '2016-04-29 01:42:39')
  SQL (0.2ms)  INSERT INTO `stocks` (`product_id`, `company_id`, `created_at`, `updated_at`) VALUES (298488079, 980193691, '2016-04-29 01:42:39', '2016-04-29 01:42:39')
  ...

=> #<Stock id: 980193023, product_id: 298488079, company_id: 980193691, created_at: "2016-04-29 01:42:39", updated_at: "2016-04-29 01:42:39">

可以看到Fabricate(:stock)不仅生成了Stock记录,还生成了与其关联的Product和Company。

更复杂的

Fabricator(:staff) do
  user
  company
end
Fabricate(:company) do
  staffs(count: 2, fabricator: :staff)
  stocks(count: 3){ |attrs, i| Fabricate(:stock){ remark: "stock#{i}" } }
end

这样会生成一个完备的公司,包括1+2+2+3+3=11条记录:

继承

如果每次要生成一个完备的公司都要写上面一大堆,岂不是很烦恼!为什么不直接定义一个表示完备公司的Fabricator呢?这个Fabricator继承自Company Fabricator,理所当然。

Fabricator(:complete_company, from: :company) do
  staffs(count: 2, fabricator: :staff)
  stocks(count: 3){ |attrs, i| Fabricate(:stock){ remark: "stock#{i}" } }
end

现在可以使用Fabricate(:complete_company)来生成一个和上面一样的公司了!

生成多个对象

Fabricate.times(10, :complete_company)

READ MORE