OSX Leopard, RSpec Autotest Growl/growlnotify Workaround

Posted by mhagedorn on October 31st, 2007 filed in Rspec

Upon loading up the new release of OSX 10.5 (Leopard), I was very frustrated to find that Growl notifications no longer work when using
Autotest. Apparently growlnotify, the command line app which makes the magic happen, isn’t compatible. Read on to see how I got this work

It turns out that there is another way to get notifications into Growl other than the the (broken) growlnotify. That technique is to use Applescript.
Applescript allows you to do all sorts of neat things to applications in OSX but it is an arcane and hard to understand beast (at least in my
opinion – feel free to flame me :) ). Based on a sample from the Growl website I was able to cobble together a working solution which
restores all the growlnotify goodness we have come to expect from Autotest. The first thing is to write the Applescript which talks to Growl.

Here is what I came up with (as modified from the Growl website)

— growlNotify.applescript

— Created by Mike Hagedorn on 2007-10-31.
— Copyright (c) 2007 Silverchair Solutions. All rights reserved. http://www.silverchairsolutions.com
— based on script from the growl website
— works around the fact that growlnotify doesnt work on leopard

— pass in like osascript growlNotify.applescript <message> <image><br /> on run argv<br /> set rspec<em>title to item 1 of argv<br /> set rspec</em>message to item 2 of argv<br /> set rspec<em>image to item 3 of argv</p> <p> tell application “GrowlHelperApp”<br /> — Make a list of all the notification types<br /> — that this script will ever send:<br /> set the allNotificationsList to ¬<br /> {”RSpec Notification” }</p> <p> — Make a list of the notifications<br /> — that will be enabled by default.<br /> — Those not enabled by default can be enabled later<br /> — in the ‘Applications’ tab of the growl prefpane.<br /> set the enabledNotificationsList to ¬<br /> {”RSpec Notification”}</p> <p> — Register our script with growl.<br /> — You can optionally (as here) set a default icon<br /> — for this script’s notifications.<br /> register as application “Growl-RSpec AppleScript Notifications” ¬<br /> all notifications allNotificationsList ¬<br /> default notifications enabledNotificationsList ¬<br /> icon of application “Script Editor”</p> <p> — Send a Notification…<br /> notify with name “RSpec Notification” ¬<br /> title rspec</em>title ¬<br /> description rspec<em>message ¬<br /> application name “Growl-RSpec AppleScript Notifications” ¬<br /> image from location rspec</em>image</p> <p> end tell</p> <p> end run</p> <p>Put this file somewhere where you can find it (I used ~/Library/Scripts/growlNotify.applescript) then modify the .autotest file you have in your home directory<br /> to not call growlnotify, but the new method you just crafted (i.e. the applescript). Here is what mine looks like</p> <p> #<br /> # .autotest<br /> # Autotest Growl Notifications for Rspec and Test::Unit<br /> #<br /> # Created by Rein Henrichs on 2007-09-12.<br /> # Modified by Mike Hagedorn (www.silverchairsolutions.com) to use osascript to work around Leopard issues<br /> #<br /> # Copyright 2007 Rein Henrichs.<br /> # http://pastie.caboo.se/96573/download<br /> # </p> <p> require ‘logger’<br /> logfile = File.join(File.dirname(<strong>FILE</strong>), ‘.autotest.log’)<br /> $logger = Logger.new(logfile)</p> <p> module Autotest::Growl<br /> Autotest.add<em>hook :ran</em>command do |at|<br /> input = Input.new( at.results )<br /> Growler.display<em>notification( input )<br /> end<br /> end </p> <p> class String<br /> def remove</em>color<em>codes!<br /> self.gsub!(/\e[\d+m/,”)<br /> self.strip!<br /> end<br /> end</p> <p> class Growler<br /> class << self<br /> def display</em>notification( input )<br /> growler = RspecGrowler if input.from<em>rspec?<br /> growler = TestUnitGrowler if input.from</em>test<em>unit?<br /> growler.display</em>notification( input.result<em>line )<br /> rescue => e<br /> $logger.fatal e<br /> notify</em>system<em>error( “Unexpected Error”, “Please check your ~/.autotest.log and report anything strange to reinh@reinh.com” )<br /> end</p> <p> def notify(title, msg, img, pri=0, stick=”" )<br /> #system “growlnotify -n autotest –image #{img} -p #{pri} -m #{msg.inspect} #{title} #{stick}”<br /> system “osascript ~/Library/Scripts/growlNotify.applescript ‘#{title}’ ‘#{msg.inspect}’ ‘#{img}’”<br /> end</p> <p> def notify</em>system<em>error( title = “System Error”, err = “”)<br /> Growler.notify( title, err, ‘~/Library/autotest/rails</em>fail.png’)<br /> end<br /> end<br /> end</p> <p> class Input<br /> def initialize(input)<br /> @input = input<br /> end</p> <p> def empty?; @input.empty?; end</p> <p> # TODO: Make these work<br /> def failing?; end<br /> def passing?; end<br /> def error?; end</p> <p> def from<em>rspec?; !!rspec</em>result<em>line || empty?; end<br /> def from</em>test<em>unit?; !!test</em>unit<em>result</em>line; end<br /> def rspec<em>result</em>line; @input.grep( /\d+\sexample/ ).first; end<br /> def test<em>unit</em>result<em>line; @input.grep( /\d+\sassertion/ ).first; end<br /> def result</em>line<br /> @line ||= case<br /> when from<em>rspec? then rspec</em>result<em>line<br /> when from</em>test<em>unit? then test</em>unit<em>result</em>line<br /> else nil<br /> end<br /> @line.remove<em>color</em>codes! if @line<br /> end<br /> end</p> <p> class AutoGrowler < Growler<br /> class << self<br /> def notify<em>failure(input)<br /> notify( “Tests Failed”, input, ‘~/Library/autotest/rails</em>fail.png’, 2 )<br /> end<br /> def notify<em>success(input)<br /> notify( “Tests Passed”, input, ‘~/Library/autotest/rails</em>ok.png’, 0 )<br /> end<br /> end<br /> end</p> <p> class RspecGrowler < AutoGrowler<br /> class << self<br /> def notify<em>pending(input)<br /> notify( “Tests Pending”, input, ‘~/Library/autotest/pending.png’, 1 )<br /> end</p> <p> def notify</em>error<br /> notify( “Syntax Error”, “It looks like there was a syntax error. Check your autotest results.”, ‘~/Library/autotest/rails<em>fail.png’)<br /> end</p> <p> def display</em>notification(input)</p> <p> notify<em>error and return unless input<br /> # TODO: replace with some object oriented goodness. elsif FTL!<br /> examples, failures, pending = input.split(”, “)<br /> if failures.to</em>i > 0<br /> notify<em>failure input<br /> elsif pending.to</em>i > 0<br /> notify<em>pending input<br /> else<br /> notify</em>success input<br /> end<br /> end<br /> end<br /> end</p> <p> class TestUnitGrowler < AutoGrowler<br /> class << self<br /> def notify<em>error(input)<br /> notify( “Tests Errored”, input, ‘~/Library/autotest/rails</em>fail.png’, 2 )<br /> end<br /> def display<em>notification( input )</p> <p> # TODO: replace with some object oriented goodness. elsif FTL!<br /> tests, assertions, failures, errors = input.split(”, “)<br /> if errors.to</em>i > 0<br /> notify<em>error input<br /> elsif failures.to</em>i > 0<br /> notify<em>failure input<br /> else<br /> notify</em>success input<br /> end<br /> end<br /> end<br /> end</p> <p>Notice that the change here is a small one, only on line 44, reference the commented out growlnotify. This is working great for me. Hope this helps<br /> you!</p></p> </p> </div> <div class="commentsblock"> <!-- You can start editing here. --> <br> <h4 id="comments">6 Responses to “OSX Leopard, RSpec Autotest Growl/growlnotify Workaround”</h4> <ol class="commentlist"> <li class="alt" id="comment-10"> <cite>Scott</cite> Says: <br /> <small class="commentmetadata"><a href="#comment-10" title="">October 31st, 2007 at 5:34 pm</a> </small> <p>Hey, the html mangled both of the scripts, and I never really used such a complex .autotest script, but the applescript works flawlessly after some character replacement. I put it in pasties:</p> <p>growlnotify.scpt – <a href="http://pastie.caboo.se/112911" rel="nofollow">http://pastie.caboo.se/112911</a> .autotest I use – <a href="http://pastie.caboo.se/112912" rel="nofollow">http://pastie.caboo.se/112912</a></p> </li> <li class="" id="comment-11"> <cite><a href='http://www.locomotivation.com' rel='external nofollow' class='url'>Wynn Netherland</a></cite> Says: <br /> <small class="commentmetadata"><a href="#comment-11" title="">October 31st, 2007 at 7:24 pm</a> </small> <p>Thanks for the tip, Mike? I wanted to ask if you did a clean install or an upgrade to 10.5? Growlnotify did not work for me after my upgrade but I quickly found out that the upgrade had dropped my /usr/local/bin path out of my $PATH…</p> </li> <li class="alt" id="comment-12"> <cite><a href='http://www.silverchairsolutions.com' rel='external nofollow' class='url'>mhagedorn</a></cite> Says: <br /> <small class="commentmetadata"><a href="#comment-12" title="">November 1st, 2007 at 5:58 am</a> </small> <p>yeah I upgraded. the growl guys confirmed it as a bug.</p> </li> <li class="" id="comment-15"> <cite>Mike Breen</cite> Says: <br /> <small class="commentmetadata"><a href="#comment-15" title="">November 27th, 2007 at 8:08 am</a> </small> <p>This solved my Growl problems on Leopard. Thanks guys.</p> </li> <li class="alt" id="comment-24"> <cite>hogmoru</cite> Says: <br /> <small class="commentmetadata"><a href="#comment-24" title="">December 6th, 2007 at 3:50 pm</a> </small> <p>Hi, I came up with another solution, a 1 line wrapper, no applescript… please tell me if it does not cover your needs, I may be missing your point here, or some aspects of it <img src='http://www.silverchairsolutions.com/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p> <ul> <li><p>In the growl prefs pane, network tab, activate incoming connections</p></li> <li><p>rename /usr/local/bin/growlnotify to /usr/local/bin/growlnotify.wrapped</p></li> <li><p>create /usr/local/bin/growlnotify as a shell script containing “exec /usr/local/bin/growlnotify.wrapped -H localhost ${1+$@}”</p></li> </ul> <p>This forces growlnotify to use the network to communicate with growl. (The script could also check that it is not already invoked with the “-H” option, I just did not need to care, maybe you would.)</p> <p>Cheers</p> </li> <li class="" id="comment-79"> <cite><a href='http://www.cybertherial.com/weblog/?p=15' rel='external nofollow' class='url'>Grumbling and Growling</a></cite> Says: <br /> <small class="commentmetadata"><a href="#comment-79" title="">February 16th, 2008 at 7:14 pm</a> </small> <p>[...] it work.My solution is a mashup of ideas from these sites, growl docs and autotest docs:UnixmonkeySilver Chair Solutions Neither of the above worked out of the box for me. (Not sure why) My solution [...]</p> </li> </ol> <h4 id="respond">Leave a Comment</h4> <p>You must be <a href="http://www.silverchairsolutions.com/blog/wp-login.php?redirect_to=http://www.silverchairsolutions.com/blog/2007/10/osx-leopard-rspec-autotest-growlgrowlnotify-workaround-2/">logged in</a> to post a comment.</p> </div> <!-- end loop --> </div> <div id="sidebar"> <div id="colTwo"> <ul> <h2> <label for="s">Search:</label></h2> <form id="searchform" method="get" action="/blog/index.php"> <div> <input type="text" name="s" id="s" size="15" /> <input type="submit" value="Go!" /> </div> </form> <br/> <h2>Meta:</h2> <ul> <li><a href="http://www.silverchairsolutions.com/blog/wp-login.php?action=register">Register</a></li> <li><a href="http://www.silverchairsolutions.com/blog/wp-login.php">Log in</a></li> <li><a href="feed:http://www.silverchairsolutions.com/blog/feed/" title="Syndicate this site using RSS"><abbr title="Really Simple Syndication">RSS</abbr></a></li> <li><a href="feed:http://www.silverchairsolutions.com/blog/comments/feed/" title="The latest comments to all posts in RSS">Comments <abbr title="Really Simple Syndication">RSS</abbr></a></li> <li><a href="http://validator.w3.org/check/referer" title="This page validates as XHTML 1.0 Transitional">Valid <abbr title="eXtensible HyperText Markup Language">XHTML</abbr></a></li> <li><a href="http://wordpress.org/" title="Powered by WordPress, state-of-the-art semantic personal publishing platform."><abbr title="WordPress">WordPress</abbr></a></li> </ul> <br/> <!-- add links of your choice --> <h2>Links:</h2> <ul> <li><a href="http://www.host2get.com" title="All the hosting providers reviews and discounts">Host 2 Get</a></li> <li><a href="http://www.28freecards.com" title="Free Quality eCard Greetings">Free eCards</a></li> <li><a href="http://www.loreleiweb.com/forum" title="Photoshop Designers Forum">Lorelei Web Forum</a></li> <li><a href="http://www.nowg.net" title="Technology and news blog">Now G Net</a></li> </ul> <br/> </ul> </div> <div id="colThree"> <ul> <h2>Categories:</h2> <ul> <li class="cat-item cat-item-8"><a href="http://www.silverchairsolutions.com/blog/category/cocoa/" title="View all posts filed under Cocoa">Cocoa</a> </li> <li class="cat-item cat-item-3"><a href="http://www.silverchairsolutions.com/blog/category/memcached/" title="View all posts filed under Memcached">Memcached</a> </li> <li class="cat-item cat-item-10"><a href="http://www.silverchairsolutions.com/blog/category/openid/" title="View all posts filed under OpenId">OpenId</a> </li> <li class="cat-item cat-item-4"><a href="http://www.silverchairsolutions.com/blog/category/rails/" title="View all posts filed under Rails">Rails</a> </li> <li class="cat-item cat-item-7"><a href="http://www.silverchairsolutions.com/blog/category/rspec/" title="View all posts filed under Rspec">Rspec</a> </li> <li class="cat-item cat-item-6"><a href="http://www.silverchairsolutions.com/blog/category/ruby/" title="View all posts filed under Ruby">Ruby</a> </li> <li class="cat-item cat-item-5"><a href="http://www.silverchairsolutions.com/blog/category/security/" title="View all posts filed under Security">Security</a> </li> <li class="cat-item cat-item-1"><a href="http://www.silverchairsolutions.com/blog/category/uncategorized/" title="View all posts filed under Uncategorized">Uncategorized</a> </li> </ul> <br/> <h2>Archives:</h2> <ul> <li><a href='http://www.silverchairsolutions.com/blog/2009/09/' title='September 2009'>September 2009</a></li> <li><a href='http://www.silverchairsolutions.com/blog/2008/04/' title='April 2008'>April 2008</a></li> <li><a href='http://www.silverchairsolutions.com/blog/2008/03/' title='March 2008'>March 2008</a></li> <li><a href='http://www.silverchairsolutions.com/blog/2007/11/' title='November 2007'>November 2007</a></li> <li><a href='http://www.silverchairsolutions.com/blog/2007/10/' title='October 2007'>October 2007</a></li> <li><a href='http://www.silverchairsolutions.com/blog/2007/09/' title='September 2007'>September 2007</a></li> <li><a href='http://www.silverchairsolutions.com/blog/2007/07/' title='July 2007'>July 2007</a></li> <li><a href='http://www.silverchairsolutions.com/blog/2006/02/' title='February 2006'>February 2006</a></li> </ul> <br/> </ul> </div> </div><!-- begin footer --> <!-- Do not deleting the credits, this theme is released for free under the GNU General Public License 2.5 (GPL) requiring that the credits will stay intact. Thank you for using my WordPress Theme! --> <!-- Footer --> <div id="footer" class="fixed"> Copyright © How they Discovered Something Worth Knowing | Powered by <a href="http://wordpress.org/">WP</a> | <a href="http://www.toptut.com/2007/04/09/free-wordpress-theme-dairy-notes">Diary Notes</a> theme released by <a href="http://www.toptut.com">Top Tut</a> and <a href="http://www.loreleiwebdesign">LW Design</a> </div> <!-- End Footer --> </body> </html>