thoughtbot / factory_bot

A library for setting up Ruby objects as test data.

Home Page:https://thoughtbot.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Expose defined factories

dmolesUC opened this issue · comments

Problem this feature will solve

I often find myself creating multiple factories for a given model, for various reasons — e.g.:

  • fields with semantic constraints that can't easily be captured in factory logic
  • references to other forms of test data such as image files
  • working with copies of production data that surfaced particular issues

— and then writing multiple specs that all reference all of those factories, or some defined subset of them.

FactoryBot does not provide any documented way of easily doing this without unnecessary repetition; there's no out-of-the-box way to say, for instance "create all defined instances of model Qux", and even if there was, that wouldn't handle the subset case.

Desired solution

  • Making FactoryBot#factories, FactoryBot::Registry and FactoryBot::Factory (at least
    some subset of their methods) stable public APIs. This would be the most flexible solution
    and most likely to address other use cases than mine.
  • Alternatively, add specific DSL methods, e.g. a create_each to create records from each
    factory nested in a given root factory. This could work, esp. if it accepted a predicate
    argument of some kind to handle subsets, but seems unnecessarily specific, and would
    presumably require corresponding build_each, attributes_for_each, etc.

Alternatives considered

  1. Current workaround: use the internal APIs anyway, and be prepared for them to break:

    all_quxes = FactoryBot.factories
      .select { |f| f.build_class == Qux }
      .map { |n| create(:n) }
    
    my_quxes = FactoryBot.factories
      .select { |f| f.build_class == Qux && f.names.any? { |n| n.start_with?('my') } }
      .map { |n| create(:n) }
  2. When working with multiple records, create only generic data using the existing list
    strategies.

    • Pros:
      • Well documented, works out of the box, no new features
    • Cons:
      • can be hard to make generic data meet semantic constraints
      • generic data is often less human-readable when diagnosing test failures
      • by its nature, generic data can't easily capture specific situations
  3. Go back to fixtures

    • Pros:
      • fixture definitions are in YAML, so we could write tooling to parse that and
        instantiate them programmatically based on whatever criteria we wanted
    • Cons:
      • all the reasons we switched from fixtures to FactoryBot in the first place