You are using an outdated browser which puts all net citizens at risk. As an incentive to upgrade to a current and thus much more secure product (we recommend the free Firefox browser), you won't be able to visit this site in its cute design, but in this rather boring printer-ready version only. Thank you for considering a browser update!

Mac-friendly Autotest

autotest

ZenTest’s autotest is great, but it has one drawback: In order to detect whether you have modified a file, it relies on filesystem polling. In other words it constantly traverses the filesystem and thus causes a lot of CPU and harddrive load. Check this out:

$ autotest &
[1] 664
$ ps ax 664
664 s000 S+ 0:00.63 /usr/bin/ruby -ws /usr/bin/autotest
-- WAIT 1 MINUTE --
$ ps ax 664
664 s000 S+ 0:01.27 /usr/bin/ruby -ws /usr/bin/autotest
            ^^^^^^^

Eventhough you don’t do anything, the CPU clock for the autotest process keeps counting up. If you are working on a portable computer, you will notice that your battery runs out in no time. And that’s not even the worst part yet. Permanent filesystem cruising are poison for the harddrive will have an impact on it’s life expectancy on the long run.

autotest-fsevent

Enter the autotest-fsevent gem. It teaches autotest to use FSEvent instead of filesystem polling. Here’s the same test with autotest-fsevent installed:

$ autotest &
[1] 698
$ ps ax 698
698 s000 S+ 0:00.63 /usr/bin/ruby -ws /usr/bin/autotest
-- WAIT 1 MINUTE --
$ ps ax 698
698 s000 S+ 0:00.63 /usr/bin/ruby -ws /usr/bin/autotest
            ^^^^^^^

As you see the CPU clock is not counting while autotest waits for file alterations. Instead of monitoring the files itself, autotest-fsevent delegates this job to the FSEvent core service which Apple has introduced with Mac OS X 10.5. Think of FSEvent as a radio station which constantly broadcasts file alterations. It comes at no extra cost as it’s sitting right on the kernel.

Installation

First install the gem:

sudo gem install autotest-fsevent

Then add the following line after all other requires in your ~/.autotest:

require 'autotest/fsevent'

Please submit feature requests and bug reports on BitForge rather than adding a comment here.

Resources

autotest-growl

ZenTest-4.0.0 comes with bundled Growl support which, however, will vanish very soon in favor of the autotest-growl gem which displays Growl notifications for RSpec, Unit::Test and Cucumber. And it comes with a cute set of colored Ruby icons which can easily be overridden by your preferred icon set.

Installation

Read the README for installation instructions as they differ whether your’re on ZenTest-4.0.0 or an upcoming version without bundled Growl support.

Please submit feature requests and bug reports on BitForge rather than adding a comment here.

References

Exceptions

The only feature which hasn’t made it from the now deprecated autotest-mac gem into neither autotest-fsevent nor autotest-growl is the exception of certain paths. It’s in fact better if you set them yourself and according to your needs in ~/.autotest. Here is an example:

Autotest.add_hook :initialize do |autotest|
  %w{.git .svn .hg .DS_Store ._* vendor}.each {|exception| autotest.add_exception(exception) }
  false
end

(Sven Schwyn)

Comments

Pirkka said on Wednesday, May 27, 2009:

this is awesome!

Bryce Thornton said on Wednesday, May 27, 2009:

This is really great. Thanks!!

I’m getting the “cannot run scenarios” message after growl tells me that my tests have all passed. I’m not using Cucumber at all. Could that be what is triggering that message?

Cucumber support is really cucumbersome at the moment. However, this should be fixed now in the offspring autotest-growl gem.

Edwin Moss said on Wednesday, May 27, 2009:

Great Stuff!

The growl tip after gem install seemed to fix my growl issues.

Now I am getting:

autotest-mac: FSEvent not available, falling back to filesystem polling.

I also got a growl notification about not being able to run scenarios.

Any help is appreciated.

Thanks!

Quite funky: Fresh installs of Mac OS X 10.5 report darwin9 while upgrades from 10.4 seems to report darwin8.9 or 8.10. I couldn’t find documentation on this, so I take your word for it and accept these platforms as well in the new offspring autotest-fsevent gem.

Jeffrey said on Wednesday, May 27, 2009:

This is great. Works great with autospec too once you’ve modified the .autotest file. Less system resources and faster response to changes. Awesome.

Tee said on Wednesday, May 27, 2009:

Thanks! Works for me alongside the redgreen gem using ruby 1.8.6 and rails 2.1.2

Ryan Davis said on Wednesday, May 27, 2009:

File system polling doesn’t take that much CPU if you’re not polling over a ridiculous amount of stuff that doesn’t actually change. The obvious candidate is a rails vendor directory with a bunch of static plugins and all of rails. That is why you should exclude patterns in your .autotest.

I may vary on different hardware, but my MacBook fans when autotest is polling – and the battery drains much faster.

it’d be nice if you broke this up into properly structured separate autotest plugins w/in the autotest name/file space so you can simply add requires to your .autotest to activate this:

require ‘autotest/...’

Done that: autotest-mac is now splitted into autotest-fsevent and autotest-growl.

Eloy Duran said on Wednesday, May 27, 2009:

Nice work!

Just wanted to point you to 2 existing libraries that you might be able to use to replace some parts. Although they do use RubyCocoa and it seems as if you don’t want to use that by reading the README. Any specific reason for that which you’d like to share? Or did I just misread it? :)

In general, I prefer the MacRuby approach. But the real problem is that I’m using Gentoo Prefix to use Ruby 1.8 and 1.9 alongside. And it’s quite tough to get RubyCocoa compiled in that setting.

Anyhoo, the libs are:

Cheers

Jeff Southard said on Wednesday, May 27, 2009:

I also get the “autotest-mac: FSEvent not available, falling back to filesystem polling.” message. I’m on a Unibody MacBook Pro with Mac OS 10.5.7 and RUBY_PLATFORM is “i686-darwin8.10.1”. Looking forward to a patch! Thanks!

Switch to autotest-fsevent (see red box above) and it should work.

Morgan said on Wednesday, May 27, 2009:

Greetings,

It’s a very nice fix, but it clears the screen between each run. I find it useful to keep that history; sometimes I need it.

You can still do that, the terminal clear sequence doesn’t affect or limit upscrolling at all. (At least not in Apple’s Terminal.app.)

It also is constantly saying, ‘can’t run scenarios’, after each run. Since I don’t use scenarios, that seems like it should be a silent fail.

This should be fixed in the offspring autotest-growl.

Both were simple to disable with quick edits in the gem, but that’ll get lost when the next time I update it.

Thanks muchly! I’ve been a little annoyed at the CPU use of autotest in the past (although adding exceptions for git’s directories resolved a lot of that, it’s still a bit high), in my case it would spike the temp of my laptop to unusable levels.

I look forward to using this more, and seeing if it helps keep my laptop’s temp under control.

— Morgan

Dean Wampler said on Wednesday, May 27, 2009:

I’m getting the same error message as Edwin on 10.5.

RUBY_PLATFORM i686-darwin8.9.1

Switch to autotest-fsevent (see red box above) and it should work.

Sascha Konietzke said on Thursday, May 28, 2009:

Great idea, however, I have the same problem as Edwin.

RUBY_PLATFORM => “i686-darwin8.10.3”

I have OS X 10.5 installed, it didn’t reinstall, it is an upgrade from 10.4.

Switch to autotest-fsevent (see red box above) and it should work.

thilo said on Thursday, May 28, 2009:

Nice. I will git it a try. So far I used Rspactor that uses FSEvent too. But it works only for RSpec. You might have a look at it http://github.com/mislav/rspactor/tree/master

Cheers

Mislav said on Thursday, May 28, 2009:

Keep an eye on RSpactor, too. Currently only supporting RSpec, but support for text/unit, shoulda and Cucumber is coming soon.

Unlike RSpactor, autotest-fsevent doesn’t depend on RubyCocoa (which is kind of hard to install on my Gentoo Prefix setup. If you don’t mind RubyCocoa, RSpactor could be an alternative for you.

Adrian Mugnolo said on Thursday, May 28, 2009:

This is awesome!

Still, I’m getting this error message from growlnotify:

2009-05-28 07:53:38.791 growlnotify[14245:613] Exception: NSPortTimeoutException

Check out the spinoff autotest-growl which now uses local Growl notifications per default as it seems to be more reliable than a while ago. If someone runs into trouble, there’s a config option to switch back to remote notifications. You find it all in the README

Jeff Southard said on Thursday, May 28, 2009:

If you get error: ”...no such file to load—autotest-fsevent (MissingSourceFile)...”

Double-check that you typed: require ‘autotest/fsevent’

Instead of: require ‘autotest-fsevent’

Eloy Duran said on Friday, May 29, 2009:

And for another shameless plug ;) I actually don’t like autotest myself anymore. So I have started on a general purpose runner-if-files-change, which will soon sport a way to load a dot file which can define a callback in Ruby.

http://github.com/alloy/kicker/tree/master

Don said on Saturday, May 30, 2009:

There is also spicycode’s beholder which uses fs-event and is an alternative to autotest.

UnderpantsGnome said on Sunday, May 31, 2009:

Thanks for these gems I moved my setup to these today.

I forked and added a couple things, feel free to grab them.

Changes:

  • Added in priorities for different results. I have my notifications colored for them (red, yellow, green)
  • Added a config for not clearing the screen on each run.

Neil said on Sunday, June 14, 2009:

I installed the gem but my Shoulda tests aren’t being picked up anymore (I just see 0 tests 0 assertions, etc). My Rails apps each seem to have their own .autotest with require redgreen, like so (but I’ve tried without redgreen and it doesn’t make a difference);

With: http://pastie.org/511872

Without: http://pastie.org/511875

With appropriate ordering: http://pastie.org/511874

These are the gem versions, and everything was running fine before the gem install;

autotest-fsevent (0.1.1) redgreen (1.2.2) thoughtbot-shoulda (2.10.1, 2.0.6) ZenTest (4.1.1, 3.10.0)

Rspec appears to work, though. However, I’ve uninstalled the gem and it seems my autotest hasn’t been reverted to the state before “sudo gem install autotest-fsevent”.

Has anyone else noticed this?

Alastair Brunton said on Tuesday, June 16, 2009:

@neil: Yes I had that problem, it turns out that rails support has been removed from ZenTest! You have to install autotest-rails to keep it working.

This is mentioned in the release notes, but often people miss these.

@bitcetera: Thanks for autotest-fsevent this is the bomb. My CPU now sits substantially lower than before.

Neil said on Thursday, June 25, 2009:

@Alastair Brunton, thank you, I’m now back on autotest & shoulda (‘rake test’ wasn’t quite as much fun).

David Rivers said on Wednesday, November 18, 2009:

Thanks for this! I’m glad I happened across this blog entry. I just installed Autotest on my Mac and am very optimistic!

Eric Wollesen said on Wednesday, February 24, 2010:

Just in case anyone reading this is running Linux and feels left out, I’ve created a similar gem for Linux using inotify

matte said on Saturday, February 27, 2010:

I found that the new lightweight autotest requires installation of the autotest-rails-pure gem if running under rails. I suggest putting that in your read me as well. links to the dependent gems would help also fyi.

thanx for this gem.

Re: I mention it on the project pages and a README update is pending.

(We are remaking our web presence and therefore comments are temporary disabled.)