Loading Fixture Data

Learn about fixtures loading, fixtures file, state fixtures, objects fixtures, and why fixtures are great.

Fixtures loading

By default, all our defined fixtures are loaded into the database once at the beginning of our test run. Rails start a database transaction at the beginning of each test. At the end of each test, the transaction is rolled back, restoring the initial state quickly.

The spec_helper.rb file fixtures

The fixtures’ transactional behavior is a problem if we’re trying to test transactional behavior in our application. In that case, the fixture transaction will overwhelm the transaction we’re trying to test. If we need less aggressive transaction behavior, we can go into the spec/spec_helper.rb file and add the line config.use_transactional_fixtures = false. There’s no way to change this behavior to be fine-grained enough to use the non-transactional behavior for only a single spec. Again, if we need to test transactional behavior, fixtures may not be our best bet.

Why fixtures are great?

Fixtures have a bad reputation in some circles, but they do have their good points. Used judiciously, fixtures are a fast way to create static background data.

Fixtures are fast

One reason to use fixtures in a modern Rails application is how fast they are. They add overhead only when the Rails framework is loaded. There’s no real cost to having fixtures persist between tests, so there’s no particular downside to having many objects defined in fixture files.

State fixtures

Well, there’s one downside: sometimes we might write a test that assumes the database table is blank, so we’d test something that’s supposed to create an object and then test that there’s exactly one object in the database. The existence of fixture data will break that test because we’ll start with objects in the database. One workaround is to explicitly test the change between the initial and ending states rather than assuming the start state is an empty table.

Objects fixtures

Fixture speed makes fixtures ideal for setting up reasonably complicated object-relationship trees that we might use in our tests. That said, if we’re truly unit-testing, we likely don’t need complicated object-relationship trees. (If we’re acceptance-testing, on the other hand, that may not be the case.)

Fixtures are always there

We can count on fixtures always being available anywhere in our test suite. In many unit-testing situations, that’s not a big deal because we don’t create a lot of data for each test.

Data static

However, some applications rely on the existence of some mostly static data that are stored in the database. Often this is metadata, product types, user types, or categories of some kind. It’s stored in the database to make it easy to modify, but it’s static data most of the time. If our application assumes that data will always be there, setting that data up via fixtures will be faster and easier than re-creating the data for each test.

Note: Fixtures are beneficial for global semi-static data stored in the database.

Get hands-on with 1400+ tech skills courses.