Creating test data with factories [1d]
- Learn to create test data effectively using factories.
- Decouple tests by having each test start with an empty database and create only the records needed for the test.
By default Rails usesfor its tests. This is a giant world of example data that grows with every test.
In our experience the use of fixtures can make a test suite hard to work with. In any non-trivial test suite there will be thousands of invisible dependencies between fixtures and test examples. E.g. to test a new edge case you make a small change to an existing fixture. Then a dozen tests break because they relied on the data you just changed.
Our favorite gem for test factories is. We used other gems in the past, but they all work in the same way.
Watchfor an introduction to factories in general and FactoryBot in particular.
This is an older video. FactoryGirl has since been renamed to FactoryBot.
Read the. Despite its name this is an in-depth guide and covers advanced use cases.
You may encounter libraries likethat creates realistic names, addresses, etc. for your sample data. This looks awesome, but at the risk of adding random strings to your screen.
Read don't build randomness into your factories for more background.
If you haven't done so already:
- Install FactoryBot via .
- is already configured to erase the test database before every RSpec example and Cucumber scenario.
You will be calling your factories a lot. Therefore it is preferrable to just say
FactoryBot.create(:movie). You can configure this like so:Copy
RSpec.configure do |config| config.include FactoryBot::Syntax::Methods end
- Write a factory for each of your MovieDB models.
- In your model specs and Cucumber features, only use factories to create your test data.
- Leverage that factories will set defaults for attributes that you don't explicitly mention. You should remove any attribute values that are not relevant to a test. E.g. if a test needs a
Moviebut does not care about its
#yearattribute, the test should let the factory fill in a default year. However, if the test checks for one particular year, it should be explicitly set in the test (even though there is a factory default).
Create a factory that works like this:
create(:movie, :biography, person: 'Al Gore')
This creates up to three records (class names may differ in your MovieDB implementation):
Moviewith with title
"Al Gore: Biography"
Actorwith the name
"Al Gore". If an actor with that name already exists, the record is re-used and no new
Rolethat links the movie and actor above. The role's
#character_nameshould also be
"Al Gore", since he would be playing himself.
Don't actually give your
Instead, use FactoryBot's transient attributes and
afterhooks to implement the factory above.
Your development team has a full backlog of feature requests, chores and refactoring coupled with deadlines? We are familiar with that. With our "DevOps as a Service" offering, we support developer teams with infrastructure and operations expertise.