«« FanConcert's Got Mail Transient Tags on FanConcert and Artists Requiring Updates »»
blog header image
Ruby on Rails 1.0 Test Performance

The new Ruby on Rails project I'm working on is giving me an opportunity to start from scratch and incorporate all of the lessons I've learned from FanConcert so far. The new project is also giving me an opportunity to try out new things with Rails with a clean slate and then incorporate those things in FanConcert. It's benefitting both projects.

An example is Ruby on Rails' testing support, which has been improved for the 1.0 release. Rails testing supports two new settings: 1) transactional fixtures and 2) not using instantiated fixtures. Both of these settings can improve the performance of unit/functional test runs, which improves the speed of development if you run the tests a lot -- and given I like to test first, I run tests a lot.

What are these two settings? First I need to explain what Rails fixtures are: they are objects that are loaded into the test database at the beginning of every test method and used during the test. Fixtures are deleted and freshly reloaded after each test method to avoid method-to-method side effects -- very important!.

Transactional fixtures leverage a database's support for transactions to rollback the database after each test method instead of deleting all of the records and reloading them. This can result in a large performance improvement, as you will see by my numbers below.

Instantiated fixtures are fixtures in the form of regular Ruby objects available in test methods as instantiated member-level objects. If you don't need to create these instantiated fixtures before each test method, you'll save time. There's another benefit to not using instantiated fixtures: readability. Here's a comparison:

@the_arcade_fire.name   #instantiated fixture
artists(:the_arcade_fire).name   #not-instantiated fixture

Sometimes the type of the object isn't this obvious, and the explicit use of the class name to access the fixure -- artists -- can help understanding tests you haven't seen in a while. The ability to read and understand code is severely underrated in my opinion.

--

What are the performance benefits? Here are the numbers for FanConcert (mean results over several runs):

Old Rails default - unoptimized:
unit tests: 16.063 seconds
functional tests: 207.559 seconds
total: 223.5 seconds

Using transactional fixtures:
unit tests: 12.088 seconds
functional tests: 102.868 seconds
total: 114.9 seconds

New Rails default - Transactional fixtures, not instantiated fixtures:
unit tests: 8.192 seconds
functional tests: 60.978 seconds
total: 69.1 seconds

As you can see, using transactional fixtures reduced the test run time almost in half. Then not using instantiated fixtures reduced the test run time almost in half again.

After using both of these settings my total test suite run is over 3 times faster! How can I not be happy with those kinds of real-world results?

Posted at January 22, 2006 at 06:28 PM EST
Last updated January 22, 2006 at 06:28 PM EST
Comments
Google
 
Search scope: Web ryanlowe.ca