thoughtbot / thoughtbot/factory_bot

Expose defined factories

Open
#1,534 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature
Dominant language
Ruby
Stars
8.2k
Forks
2.6k
PR merge metrics
No merged PRs in 30d

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing the current FactoryBot.factories, FactoryBot::Registry, and FactoryBot::Factory interfaces referenced in the issue, along with the existing list strategies. Compare stabilizing those APIs with adding create_each, build_each, and attributes_for_each, including subset selection; done requires an agreed public approach rather than relying on internal APIs.

Written by the indexing model from the issue text.

Assessment

Tech stack
ruby
Domain
testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.