Time your Rails tests

13 Oct 2007

As a project gets bigger the tests take longer. There’s no getting around that. So unless you want to abandon testing entirely it might help to see who’s eating all those cpu cycles.

in test/test_helper.rb:

    class Test::Unit::TestCase

      def run_with_timing(*args, &block)
        @timer = Time.now
        run_without_timing(*args, &block)
        puts "#{Time.now - @timer} - #{self}"
      end
      alias_method_chain :run, :timing if ENV['TIMER']

    end

And run it like so:

    $ rake TIMER=true
    # or, to see the 10 slowest tests:
    $ rake test:units TIMER=true 2>/dev/null | grep " - " | sort -r | head -n 10

And if you really want to air the dirty laundry:

    $ grep -R 'def test_truth' test/ | grep -v .svn
  • Ted said: Note that your top ten command line example is just the slowest *unit* tests -- I should know since I wrote it ;-P You'll be hearing from my lawyers ;-) Ha ha!
  • topfunky said: I published a gem that does something similar. It's called test_timer: http://rubyforge.org/frs/shownotes.php?group_id=1513&release_id=7478
  • Jack Danger said: topfunky: I tried the version of that code that you had on your blog and for some reason it didn't work or play well with mine. The gem works great though - thanks for pointing it out!
  • Paul Hinze said: Cool idea! Inserting this into the test_helper.rb in my project caused an infinite loop though ('stack level too deep' error) because the code was being loaded more than once. I just added an extra variable to make sure this didn't happen, and everything started working:
    if ENV['TIMER'] && !ENV['TIMING_ON']
      ENV['TIMING_ON'] = true.to_s
      alias_method_chain :run, :timing   
    end
    

Please if you found this post helpful or have questions.