thoughtbot / thoughtbot/factory_bot
Allow specification of default assocations depending on context
Nobody has claimed this yet.
- Dominant language
- Ruby
- Stars
- 8.2k
- Forks
- 2.6k
- PR merge metrics
- No merged PRs in 30d
Description
Problem this feature will solve
FactoryBot allows us to easily define associations that should automatically be constructed when creating or building a model. These associations are statically defined in the Factory.
If I want to change which object is used in an association I can overwrite the association when constructing an object, but I have to do that each time I want to create something. To illustrate, consider these factories:
factory :post do
text { 'text' }
end
factory :comment do
text { 'comment' }
association :post
end
It may be fine to automatically construct a new post for every comment most of the time, but there are contexts (e.g. a small set of tests) where I always want to use a specific post. I then have to specify the association manually in each test:
def setup
@post = create(:post)
end
test 'first test' do
create(:comment, post: post)
create(:comment, post: post)
...
end
# Imagine tons of similar tests like that below...
I would like a solution that allows greater flexibility than what is currently there.
Desired solution
TestProf provides a Factory Default helper.
It should be possible to specify a set of associations to be used in a context, e.g. a block or a test class / Rspec context, using a helper method use_factory_defaults (or similar)
The tests above could then be rewritten as:
def setup
@post = create(:post)
use_factory_defaults(post: @post)
end
test 'first test' do
create(:comment) # These then use @post automatically
create(:comment)
...
end
or alternatively, for a single test:
test 'first test' do
use_factory_defaults(post: create(:post)) do
create(:comment) # These then use @post automatically
create(:comment)
end
end
Alternatives considered
It is of course possible to simply use FactoryProf. However, I feel that this specific functionality would work nicely in FactoryBot itself.
As outlined above, create(:comment, post: post) is verbose when many similar models are created.
I have considered that one may be able to hack something together with traits, but I'm not even sure how. I couldn't come up with anything 😅
Additional context
TestProf provides additional helpers such as create_default, which are essentially shortcuts to the functionality outlined above.
There are parts of this feature that are strictly RSpec/Minitest specific (e.g. cleaning up defaults after a test suite is done using framework specific hooks). Including those in FactoryBot is not required.
I already have some helpers cobbled together for Minitest (since TestProf only comes with Rspec integration), and I'd be prepared to port the TestProf functionality to FactoryBot if desired 🙂
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading TestProf’s lib/test_prof/recipes/rspec/factory_default.rb, which is linked as the reference implementation. Compare its context and cleanup behavior with FactoryBot’s association handling, then define the supported use_factory_defaults API. Done means scoped defaults work for the shown create(:comment) calls without per-call overrides, with coverage for the supported usage.
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
- 35/100