Using Factories and Fixtures to Write Great Software Tests

Daniel Pericich
3 min readJun 30, 2021

--

Photo by Science in HD on Unsplash

Good tests revolve around great data. How you get or generate this data can occur in many different ways. For Ruby on Rails, two of the most common ways to get data for testing are factories and fixtures. Though both of these strategies create data that can be used across tests, they do it in different ways.

Before we dive into the benefits and drawbacks of features and fixtures let’s first look at what they are. A fixture is “the fixed state used as a baseline for running tests in software testing.” This often takes form in a YAML file that serves as a snapshot of the data that we want to test with and is very static.

A factory is “an object used for creating other objects.” Factories used in OOP are classes that create an object with a certain set of attributes and data at creation. These can be regular objects, or models if you are using Rails. Testing provides certain challenges that can be eased by using gems such as factory bot when managing factories.

Both factories and features can be used to create data, but how do we know the best time to use either? Let’s take a look!

Fixtures

Let’s first talk about fixtures. Fixtures are great if you have a one off item that you are wanting to test. If you are doing a one time file load from a legacy endpoint to your new system, you probably don’t want to spend time creating and testing a factory. You know what your data will look like and can rely on it not changing. This is a perfect job for a fixture.

Another area fixtures excel at are situations when you will need to reset data after every test. As we will talk about later with factories, testing is prone to issues dealing with mutated objects. Fixtures address this problem by loading a fresh copy of the data for every test. No worrying about carrying over the last test’s changes!

A main drawback of fixtures is one of their strengths. Unfortunately fixtures are very static. If you are doing one offs this is a great feature, but for code that will evolve with features and customer demands, this can cause a huge headache. Any changes in new columns, or different attribute names will likely cause all of your fixture reliant tests to fail. If you want to avoid this then you can use or next item: factories.

Factories

While factories may take more time and thought to develop, they are a lot more flexible than fixtures. If you want to add a new attribute or change an attribute type, no worries because factories are easily changeable in their single source of truth files.

One downside of factories is that you will have to pay attention to their scope if you plan to carry a factory through multiple tests. While you can avoid mutated state slipping though your tests by using well placed “before” blocks, factories will take more thought as you will need to make sure that your scope on these blocks correctly resets your factory objects between tests.

Another downside is the amount of time to correctly develop the factories. While they are flexible with items like traits for creating permutations of a base factory, factories take time to think through and develop. If you have questions during development, please refer to the factory bot README on Github.

Final Thoughts

Testing doesn’t have to be overly complicated or time consuming. Factories and fixtures are both great options for avoiding repetitive coding of test objects and data. I hope that after reading this article you have a new tools to help write good tests and even better software!

Notes

https://en.wikipedia.org/wiki/Test_fixture

https://en.wikipedia.org/wiki/Factory_(object-oriented_programming)

https://api.rubyonrails.org/v3.1/classes/ActiveRecord/Fixtures.html

https://stackoverflow.com/questions/7786207/whats-the-difference-between-a-fixture-and-a-factory-in-my-unit-tests

--

--

Daniel Pericich
Daniel Pericich

Written by Daniel Pericich

Former Big Beer Engineer turned Full Stack Software Engineer

No responses yet