factory bot的使用说明


https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#implicit-definition


  1.  factory_bot 配置你的测试套件 test suite, RSpec
  2.  定义 factories( name, attributes...  best practices)
  3.  使用 factories(构建 strategies, build stragegies 覆盖属性) 什么是strategies? 策略,构建策略是什么意思? build, create, attributes_for and  build_stubbed:
  4.  factories 的别名让factory更容易被使用 factory :user, aliases: [:author, :commenter]
  5. 过渡属性: Transient 属性,临时属性,With other attributes, With attributes_for, With callbacks, With associations。
  6. 方法名/保留字,可以定义attribute,通过add_attribute(:method) {'paypal'}
  7. 继承 inheritance, 通过 factory嵌套的声明,或者 factory :approved_post, parent: :post do  声明parent:
  8. 继承的最佳实践,声明一个basic factory 只包含需要创建的属性,factory继承父类。保持代码整洁。
  9. factory之间的关联, 隐式/显式: implicit/explicit definition, 定义关联factory的位置可以在factory里面,也可以声明 author;  association :author; association: author, factory: :user; author {association :user}
  10. 覆盖属性,你也可以覆盖属性, author factory: :author, last_name: 'Writely', association :author, last_name: "Writely"
  11. build strategy里面的 parent-children关联问题,,默认build父,子也一同build,子build不成功。可以设置:FactoryBot.user_parent_strategy = false. 同样也可以在factory里面定义build策略:association :author, factory: :user, strategy: :build, implicit 隐式的关联不能声明strategy: :build
  12. has_many 关联,这里有一些方式去生成has_many关系,最简单的approach is写一个helper method  in plain Ruby 去tie together the different records:   create_list
  13. has_and_belongs_to_many 的多种声明方式,polymorphic 关联的声明方式
  14. sequence,sequence, sequence, 序列,自增ID的意思,generate(:email),就会增加一个新的email,比如 person10@example.com...person11@example.com/ sequence(:email, 1000); sequence :priority, %i[low, medium high, urgent].cycle.   sequence 还可以和aliases结合使用。 rewind_sequences, 会从1从头开始。
  15. Traits 特征和函数对应,允许你去group 属性 together, 然后应用他们到任何一个factory.  trait :published do published{true} end ; factory :week_long_published_story,    traits: [:published, :week_long_publishing]  
  16. trait...相关的一些功能attributes, enum
  17. callbacks, after(:build){|user| generate_hashed_password(user)}  multiple callbacks; after(:create)..; Global callbacks: FactoryBot.define do  after(:build){|object| puts "..."}; Symbol#to_proc...:  after :create, &:confirm!
  18. 修改factories.  FactoryBot.define , Factory.modify 必须在 define的block外面。
  19. 创建多个记录, built_users = build_list(:user, 25)
  20. Linting Factories,  linting 是什么意思?
    FactoryBot.lint creates each factory and catches any exceptions raised during the creation process. FactoryBot::InvalidFactoryError is raised with a list of factories (and corresponding exceptions) for factories which could not be created.
  21. 自定义结构Custom Construction:  initialize_with (User.build_with_name(name))
  22. 自定义策略Custom Strategies,扩展strategies, ,策略定义两个方法: association 和 result.association ,  delegate :association, to: :@strategy
  23. 自定义回调Custom Callbacks, 自定义callbacks如果你用自定义策略的话。callback(:make_json_awesome) {|user_json| do_something_to(user_json)}
  24. 自定义方法to持久化对象 to_create{ |instance| instance.persist! } 默认的设置时,创建一个record时,instance会调用save!,
  25. ActiveSupport Instrumentation
  26. Rails Preloaders and RSpec

# lib/tasks/factory_bot.rake
namespace :factory_bot do
  desc "Verify that all FactoryBot factories are valid"
  task lint: :environment do
    if Rails.env.test?
      conn = ActiveRecord::Base.connection
      conn.transaction do
        FactoryBot.lint
        raise ActiveRecord::Rollback
      end
    else
      system("bundle exec rake factory_bot:lint RAILS_ENV='test'")
      fail if $?.exitstatus.nonzero?
    end
  end
end


#Return a User instance that's not saved
user = build(:user)
# Returns a saved User instance
user = create(:user)
#Returns a hash of attributes that can be used to build a User instance
attrs = build_stubbed(:user)
# Passing a block to any of the methods above will yield the return object
create(:user) do |user|
  user.posts.create(attributes_for(:post))
end




===============Factory name and attributes
每个factory 有个一名字和一组属性。 默认情况下这个name是用来猜测对象的class
#This will guess the User Class
FactoryBot.define do 
  factory :user do 
    first_name {"John"}
    last_name {"Doe"}
    admin { false }
  end
end

:user  和 里面的一组attributes 组成了 一个factory.

Specifying the class explicitly
it is also possible to explicitly specify the class:
指定对应的类
# This will use the User class  (otherwise Admin would have been guessed) 如果不指定,那就是Admin class
factory  :admin, class:  "User"

factory ;program do 
  configuration {{  auto_resolve: false, auto_define: true }}
end

最佳实践
每个class都见一个factory,提供简单的一组属性,去创建一个类的实例
如果你创建ActiveRecord objects,那就意味着你应该提供可以通过且没有默认值的validations属性。 其它factories能够被创建通过继承来覆盖普通的场景。 
Attempting 去定义多个factories 通过相同的名字会raise an error.



阅读量: 474
发布于:
修改于: