I finally found some time to familiarize myself with RSpec by working through the excellent PeepCode RSpec screencasts (part 1, part 2, and part 3). In his screencasts, Geoffrey is using Growl for displaying notifications of autotest.
I wanted something similar and found a few examples explaining how to use notify-send from libnotify. While this is pretty easy to implement, it is just not flexible enough.
After some more searching I found an article by Derek Berner about ruby-libnotify doing more or less exactly what I want. The only problem was, that I couldn’t get his code working on my computer running Ubuntu 7.10. So I decided to write my own autotest configuration and now enjoy nice autotest notifications.
The status symbol in the notification area additionally shows the last autotest result as a tooltip.
Before you can use ruby-libnotify, you have to install the latest version of Ruby-GNOME2. I’m using version 0.16 which comes with Ubuntu 7.10. To install it, simply run
sudo aptitude install ruby-gnome2 |
If you are using Ubuntu 7.04 or another GNU/Linux distribution make sure to use at least Ruby-GNOME version 0.16, ruby-gnome2-all-0.16.0.tar.gz should do the trick.
Additionally you must install some development libraries
sudo aptitude install build-essential ruby1.8-dev libnotify-dev |
Now you have to install ruby-libnotify. I’m using version 0.3.3. To install ruby-libnotify, extract the package and execute the following commands inside the new directory:
1 2 3 |
ruby extconf.rb make sudo make install |
Now you can add the following code to your ~/.autotest configuration:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
require 'rnotify' require 'gtk2' module Autotest::RNotify class Notification attr_accessor :verbose, :image_root, :tray_icon, :notification, :image_pass, :image_pending, :image_fail def initialize(timeout = 5000, image_root = "#{ENV['HOME']}/.autotest_images" , verbose = false) self.verbose = verbose self.image_root = image_root puts 'Autotest Hook: loading Notify' if verbose Notify.init('Autotest') || raise('Failed to initialize Notify') puts 'Autotest Hook: initializing tray icon' if verbose self.tray_icon = Gtk::StatusIcon.new tray_icon.icon_name = 'face-monkey' tray_icon.tooltip = 'RSpec Autotest' puts 'Autotest Hook: Creating Notifier' if verbose self.notification = Notify::Notification.new('X', nil, nil, tray_icon) notification.timeout = timeout Thread.new { Gtk.main } sleep 1 tray_icon.embedded? || raise('Failed to set up tray icon') end def notify(icon, tray, title, message) notification.update(title, message, nil) notification.pixbuf_icon = icon tray_icon.tooltip = "Last Result: #{message}" tray_icon.icon_name = tray notification.show end def passed(title, message) self.image_pass ||= Gdk::Pixbuf.new("#{image_root}/pass.png", 48,48) notify(image_pass, 'face-smile', title, message) end def pending(title, message) self.image_pending ||= Gdk::Pixbuf.new("#{image_root}/pending.png",48,48) notify(image_pending, 'face-plain', title, message) end def failed(title, message) self.image_fail ||= Gdk::Pixbuf.new("#{image_root}/fail.png", 48,48) notify(image_fail, 'face-sad', title, message) end def quit puts 'Autotest Hook: Shutting Down...' if verbose #Notify.uninit Gtk.main_quit end end Autotest.add_hook :initialize do |at| @notify = Notification.new end Autotest.add_hook :ran_command do |at| results = at.results.last unless results.nil? output = results[/(\d+)\s+examples?,\s*(\d+)\s+failures?(,\s*(\d+)\s+pending)?/] if output failures = $~[2].to_i pending = $~[4].to_i end if failures > 0 @notify.failed("Tests Failed", output) elsif pending > 0 @notify.pending("Tests Pending", output) else unless at.tainted @notify.passed("All Tests Passed", output) else @notify.passed("Tests Passed", output) end end end end Autotest.add_hook :quit do |at| @notify.quit end end |
As icons for the notifactions I’m using the Autotest Growl Fail/Pass Smilies. If you want to use different icons in the notification area or the default ones are not found on your system, you can replace face-monkey, face-smile, face-plain, and face-sad in the above code with your own. Use Derek Berner’s icon browser to find out which icons are available on you system.
You can download my version of ~/.autotest which also includes support for Test::Unit and the nice smilies. To use it, simply unzip autotest-libnotify.zip and move the included autotest-libnotify/.autotest and autotest-libnotify/.autotest_images to your home directory.
Looks great! I was initially opposed to the idea of seeing little notifications every time my tests run, but now I appreciate it. It's a great piece of feedback, especially if it happens in a small area of the screen.
Nice work! This is what I am looking for.
But got problem in this:
"Now you have to install ruby-libnotify. I’m using version 0.3.3. To install ruby-libnotify, extract the package and execute the following commands inside the new directory:
sudo aptitude install build-essential ruby1.8 ruby1.8-dev
ruby extconf.rb
make
sudo make install"
I entered the dir, but there is no extconf.rb, here is what I got:
files ruby-libnotify-0.3.1.ebuild
Manifest ruby-libnotify-0.3.2.ebuild
ruby-libnotify-0.2.0.ebuild ruby-libnotify-0.3.3.ebuild
ruby-libnotify-0.3.0.ebuild
any suggestion?
Hi leon
I was linking to the wrong file in the article. You can download the correct archive from here. I updated the article accordingly.
I’m running the latest version of Rspec and I had to modify the regular expression to handle the case where you have an error with no pending tests.
Thank you! very very helpful.
One little thing, It seems to fail when all tests passed and there are pending tests, but anyway you saved me a lot.
Thanks for the linkback and shout-out, and for improving on my ideas!
Cool. Seems like overkill to have to compile the bindings for notifications though; I’ve done the same thing by just shelling out, and it works just as well with much less setup hassle.
I’ve followed instructions but when I run ruby extconf.rb I get the error message “ERROR: no gtk2.rb found”
I installed ruby from source, but ran apt-get install ruby1.8-dev so I’m thinking that extconf.rb can’t find something in the sitelibdir or sitelibdir directories.
Any ideas? How can I override those two locations when calling ruby extconf.rb?
I have the same problem that Wes had when installing. Maybe something have moved from where it used to be. I’ve looked at my entire disk but i cannot find gtk2.rb. I’ve installed both ruby1.8 and ruby1.8-dev from apt-get.
If i can fix that, i’ll postback here.
Thanks!
Did you install Ruby-GNOME2? On my Ubuntu 7.10 system,
gtk2.rbbelongs to the packagelibgtk2-ruby1.8:I’ve installed Ruby-Gnome2. The problem was that i did not had multiverse repository enabled at this box.
In any other machine i’ve tried to repeat these steps, everything worked smoothly.
Thanks for your help!
Thanks for sharing this. So far it seems to work great and it’s one less reason for me to feel like I should use OS X for Rails work instead of Ubuntu
Just integrated your autotest-setup in ubuntu-hardy - it works great!
here is another a version without so much installation