Non-Rails Autotest + RSpec + LibNotify + Linux

Update: The information below is VERY outdated. Take a look at new instructions for getting this set up.

Each of those terms actually means something! If you don’t know what any one of those terms means, then you probably won’t enjoy this post.

It’s surprising that something so cool and so central to the Ruby TDD world as Autotest is completely undocumented. Autotest with Rails and RSpec just works, and there are many googleable examples of how to add hooks for using Growl or libnotify. I couldn’t find any reliable advice for how to use Autotest with a non-Rails project and how to use RSpec instead of Unit/Test. The libnotify part is easy once the other two are solved, but I’ll share what I have going on anyway. This information may be available in pieces somewhere else, but I’ll just put it all here to help the other lost googlers.

The first thing to know is that this blog post is out of date. Autotest now speaks RSpec as one of its native “styles”. The trick is that you have to tell autotest about this style by creating a file called autotest/discover.rb in your project root. This contains:

Autotest.add_discovery do
  "rspec"
end

The second thing to know is that Autotest looks in your lib/ folder for your files and in your spec/ folder for your tests, which should be called
file_name_spec.rb.

There’s not much more to know. You can add awesome heads-up notification using libnotify. You need to get libnotify-bin using something like sudo apt-get install libnotify-bin. Then in the root of your project directory create an .autotest file like this:

module Autotest::GnomeNotify
 
  # Time notification will be displayed before disappearing automatically
  EXPIRATION_IN_SECONDS = 2
  ERROR_STOCK_ICON = "gtk-dialog-error"
  SUCCESS_STOCK_ICON = "gtk-dialog-info"
 
  # Convenience method to send an error notification message
  #
  # [stock_icon]   Stock icon name of icon to display
  # [title]        Notification message title
  # [message]      Core message for the notification
  def self.notify stock_icon, title, message
    options = "-t #{EXPIRATION_IN_SECONDS * 1000} -i #{stock_icon}"
    system "notify-send #{options} '#{title}' \"#{message}\""
  end
 
  Autotest.add_hook :red do |at|
    example_text = ""
    num_examples = 0
    examples = at.files_to_test.each_pair do |key, values|
      example_text += "- #{key}\n"
      values.each do |value|
        num_examples += 1
        example_text += "  * #{value}\n"
      end
    end
    notify ERROR_STOCK_ICON, "Tests failed", "<strong>#{num_examples} examples failed in #{at.files_to_test.size} files</strong>\n#{example_text}"
  end
 
  Autotest.add_hook :green do |at|
    notify SUCCESS_STOCK_ICON, "All tests passed, good job!", ""
  end
end

I’ve modified mine to have very verbose notifications. I got it from here.