Including Dynamic Data in Fixtures with ERb

Problem

Your tests often need to make a distinction between recently created or updated items and older ones. In creating test fixtures, you want to use the date helpers in Rails to dynamically generate date information.

Solution

In your YAML fixture file, include Ruby within ERb output tags. The following template produces dates for the text fixtures that remain relative to the current time:

recent_laptop_listing:
 id: 1
 title: Linux Laptop
 description: A nice laptop fully loaded and running GNU/Linux
 created_at: <%= (Date.today - 2).to_s %>
 updated_at: <%= (Date.today - 2).to_s %>
older_cellphone_listing:
 id: 2
 title: Used Cell Phone
 description: A nicely equipped cell phone from last year
 created_at: <%= (Date.today - 30).to_s %>
 updated_at: <%= (Date.today - 30).to_s %>

Another common use of Ruby in YAML fixtures is to create larger sets of test data without repetitive typing. "Don't repeat yourself" applies to test fixtures, too.

<% for i in 1..100 %> 
item_<%=i%>:
 id: <%= i %>
 name: <%= i %> year old antique 
 description: This item is <%= pluralize(i, "year") %> old
<% end %>

Discussion

The fixtures in the solution are processed by the ERb engine, which produces the following output:

recent_laptop_listing:
 id: 1
 title: Linux Laptop
 description: A nice laptop fully loaded and running GNU/Linux
 created_at: 2006-03-17
 updated_at: 2006-03-17
older_cellphone_listing:
 id: 2
 title: Used Cell Phone
 description: A nicely equipped cell phone from last year
 created_at: 2006-02-17
 updated_at: 2006-02-17

item_1:
 id: 1
 name: 1 year old antique
 description: This item is 1 year old item_2:
 id: 2
 name: 2 year old antique
 description: This item is 2 years old item_3:
 id: 3
 name: 3 year old antique
 description: This item is 3 years old
...

When tests are run, any included YAML fixture files get parsed by the ERb template engine. So you can include Ruby code between ERb output tags (<%= %>) for output generation and flow control or anything else that Ruby lets you do.

Using Ruby code embedded in your fixtures can be convenient but is generally considered bad coding practice. With too much logic embedded within your tests, you run the risk of creating tests that need as much maintenance as the application itself. If you have to spend time updating or repairing your fixtures, you're less likely to run your tests regularly.

See Also