UPDATE – Meow, a gem that really simplifies messaging to Growl, has been released. With regards to the article below, it would replace the growlnotify steps.
First off, if you are not running autotest then you need to start. It’s awesome and a pretty integral part of my TDD workflow. A popular combination these days is to run a combination of autotest along Growl. There are already quite a few guides out there on how to set up a development environment with autotest and Growl—why am I writing this one? It is because many of the guides out there do not work exactly right under OS X 10.5.2, making it frustrating to set up these tools. After trying a number of them, and taking what worked right and what didn’t, here is what works for me.
Setting up Autotest
Autotest is part of the ZenTest suite, which should be installed as a gem:
sudo gem install ZenTest
After you install the ZenTest gem, you should then have autotest at /usr/bin/autotest.
Setting up Growl
You can download Growl from the Growl website of course. You will want to install the Growl application normally, but then after that is complete, you will also want to install the growlnotify extra that comes with Growl.

Once you’ve installed Growl and while the DMG is still open, open up a Terminal.app window and execute the following:
cd /Volumes/Growl\ 1.1.2/Extras/growlnotify/ ./install.sh
Now you should be able to test this out by typing the following into the Terminal.ap window:
echo "Hello World" | growlnotify
If you receive a “growlnotify: command not found”, then you need to add /usr/local/bin into your PATH environment variable.
If this fails silently, that is because of an incompatibility between Growl and OS X 10.5.x that will cause dropped messages about 50% of the time. So even if you got the Growl notification, you should install the following fix for Growl.
Fixing Growl
Simply put, on OS X 10.5.x, growlnotify works about 50% of the time for me. To address this, first open up your Growl preferences (under System Preferences), click the network tab, and then make sure that the “Listen for incoming notifications” checkbox is checked. Like this:

After you set that, click back to the General tab, and then Stop Growl, and Start Growl again.
Now, the bug in Growl that I mentioned does not affect incoming network Growl notifications. So we’re going to make a wrapper for growlnotify that will forward received growl notifications to the network port that Growl listens on. Create ~/safegrowlnotify with the contents:
#!/bin/bash
# growlnotify leopard bug workaround
list_args()
{
for p in "$@"
do
if [ "${p:0:1}" == "-" ];then
echo -n "$p "
else
echo -n "\"$p\" "
fi
done
}
argstr=$(list_args "${@:$?}")
echo "-H localhost $argstr" | xargs /usr/local/bin/growlnotify
And of course you will want to chmod 755 that file. To test that you have it configured, run thusly:
safegrowlnotify 'Hello World!'
You should have growl notifications coming up now:

Configuring Autotest for Growl
Now that we have everything installed, it’s time to configure Autotest. When Autotest loads up and starts the test loop, it will configure itself from ./.autotest and also ~/.autotest. It is in the latter that we’ll make our Growl modifications. This way the behavior will be shared amongst all projects that use Autotest.
Insert the the following into ~/.autotest (create if it does not already exist):
.autotest
module Autotest::Growl
GROWLNOTIFY = "/Users/collin/safegrowlnotify"
def self.notify title, msg, img, pri=1, sticky=""
commands = ["#{GROWLNOTIFY} --image #{img} -p #{pri} -m #{msg.inspect} #{title} #{sticky}"]
commands.each { |c| system(c) }
end
Autotest.add_hook :ran_command do |at|
results = [at.results].flatten.join("\n")
# rpsec
output = results.slice(/(\d+)\s+examples?,\s*(\d+)\s+failures?(,\s*(\d+)\s+pending)?/)
if output
if $~[2].to_i > 0
notify "Test Results", "#{output}", "~/Library/autotest/rails_fail.png", 2
else
notify "Test Results", "#{output}", "~/Library/autotest/rails_ok.png"
end
end
# test::unit
output = results.slice(/(\d+)\s+tests?,\s*(\d+)\s+assertions?,\s*(\d+)\s+failures?,\s*(\d+)\s+errors?/)
if output
if (($~[3].to_i > 0) or ($~[4].to_i > 0))
notify "Test Results", "#{output}", "~/Library/autotest/rails_fail.png", 2
else
notify "Test Results", "#{output}", "~/Library/autotest/rails_ok.png"
end
end
end
end
(thanks to samsm for the Test::Unit modifications)
It is very important to change the value of GROWLNOTIFY to whereever you installed it previously. Also, you will want to put the following into ~/Library/autotest (create if it does not already exist). You can use whatever images you’d like, but I used these that some other kind soul before me shared in a similar blog post:

At this point, you should be all set up and ready to go. Simply running autotest should run the tests and then display the Growl messages along with an icon to boot that signifies success or failure:

Happy Autotesting!

thx a lot. very useful!
This is pretty awesome seeing as I didn’t know there was a problem with Growl and such on Leopard. I’ve been trying to get this whole thing working for a while on 10.5.x. It worked with a project I worked on in 10.4.9, but I finished that project and sort of forgot about BDD for a bit.
What versions of all the necessary gems and plugins are you using? I’ve followed these directions exactly and a bunch of others and I still get errors. Running autotest this way ends up reporting that I have failing tests when I don’t, etc.
I have ZenTest 3.9.3 installed with rspec 1.1.3 and redgreen 1.2.2.
I’m really trying to figure out if there are somehow bugs in those that I don’t know about…
Thx!
Update
Meow , a gem that makes messaging to Growl easy, has been released. This should reduce the need to use growlnotify and its variants.