ikhono.net

Gnome autotest Notifications 14

Posted on Sunday, December 16

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.

Notify

The status symbol in the notification area additionally shows the last autotest result as a tooltip.

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.

Comments

Leave a response

  1. topfunky
    topfunkyDecember 20, 2007 @ 03:39 AM

    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.

  2. leon
    leonDecember 22, 2007 @ 05:41 PM

    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?

  3. thom
    thomDecember 22, 2007 @ 06:08 PM

    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.

  4. Economysizegeek
    EconomysizegeekDecember 31, 2007 @ 05:13 PM

    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.

    Autotest.add_hook :ran_command do |at|
      results = at.results.flatten.join(“\n”)

    unless results.nil? output = results.match(/(\d+)\sexample[s]?,\s(\d+)\sfailure[s]?,\s(\d+)\spending/) unless output output = results.match(/(\d+)\sexample[s]?,\s(\d+)\sfailure[s]?/) end failures = 0 pending = 0 test_results = "" if output test_results = output[0] failures = output[2].to_i if output[3] pending = output[3].to_i end end if failures > 0 @notify.failed("Tests Failed", test_results) elsif pending > 0 @notify.pending("Tests Pending", output) else unless at.tainted @notify.passed("All Tests Passed", test_results) else @notify.passed("Tests Passed", test_results) end end end end
  5. Manuel
    ManuelJanuary 03, 2008 @ 10:07 AM

    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.

  6. Derek Berner
    Derek BernerJanuary 13, 2008 @ 08:14 PM

    Thanks for the linkback and shout-out, and for improving on my ideas!

  7. Phil
    PhilJanuary 20, 2008 @ 02:01 AM

    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.

  8. Wes
    WesFebruary 11, 2008 @ 12:35 AM

    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?

  9. Vitor
    VitorFebruary 11, 2008 @ 03:25 PM

    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!

  10. thom
    thomFebruary 11, 2008 @ 08:40 PM

    Did you install Ruby-GNOME2? On my Ubuntu 7.10 system, gtk2.rb belongs to the package libgtk2-ruby1.8:

    [thom@zaphod] ~ $ dpkg -S /usr/lib/ruby/1.8/gtk2.rb
    libgtk2-ruby1.8: /usr/lib/ruby/1.8/gtk2.rb
    
  11. Vitor
    VitorFebruary 19, 2008 @ 01:08 AM

    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!

  12. Jim
    JimMarch 14, 2008 @ 11:12 AM

    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

  13. Falk Pauser
    Falk PauserApril 22, 2008 @ 11:29 PM

    Just integrated your autotest-setup in ubuntu-hardy - it works great!

  14. grosser
    grosserMay 11, 2008 @ 07:55 AM
Comment