Automated Python testing with nose and tdaemon

If you're testing your code at all (and you are, right?), it's awfully convenient to automatically have your test suite run whenever something in your project changes. This is particularly handy if you're doing test-driven development (TDD), where you'll be writing a lot of tests and need immediate feedback on them.

With Python this is made easy with the help of nose and tdaemon.

In a hurry? Jump straight to the summary!

Installing

Both tdaemon and nose can be installed via Cheeseshop (or "PyPI", for the suits), using pip:

sudo pip install nose tdaemon

(You might not need sudo, depending on your setup).

An interlude: pip versus easy_install

You can use easy_install instead of pip. It should work just fine, for what we're trying to do here. But do yourself a favor and switch over to pip. It's as simple as

sudo easy_install pip

Another interlude: whither tdaemon?

If you google "tdaemon", the first result is a github tree from Bruno Bord, tdaemon's author. The version at Cheeseshop (yes, I'll keep calling it "Cheeseshop", damn it!) lists John Paulett as author and points back to the github repository as its home page. Both versions are almost exactly alike, except that the Cheeseshop one has a slight enhancement (a command-line argument to ignore specific directories). John Paulett took tdaemon, added that feature and packaged it for Cheeseshop. So we'll use his version.

Getting cute notifications

So far, if you simply execute tdaemon on a terminal, it'll monitor the current directory and run nosetests whenever it detects a change. Which is fine, but I don't want to switch to the terminal all the time while I'm programming, if I don't have to. So let's arrange our environment so that we get visual alerts every time the tests are run.

On Mac OS X

I assume you already have Growl on your Mac. If you don't, install it, it makes your life easier (if you don't know, it should be at the bottom row on your System Preferences panel).

The NoseGrowl nose plugin provides Growl notifications. Unfortunately, NoseGrowl installation from PyPI is currently broken: there is only an egg for Python 2.5 on Cheeseshop. The original source code on bitbucket has a bug on setup.py, but Osvaldo Santana was kind enough to fork and fix it. So:

hg clone http://bitbucket.org/osantana/nosegrowl
cd nosegrowl/nose-growl
sudo python setup.py install

By the way, NoseGrowl's author, Victor "crankycoder" Ng, told me a few months ago that he was looking for someone to take over for him. So, if you find the project useful, please consider talking to Victor and volunteering to maintain it. Might make him less cranky :) [Edit: perhaps Osvaldo will step up?]

On Linux (Gnome)

There is a NoseGrowl-inspired plugin adapted to use Gnome's notification system. It's called nose-notify and can be installed directly from Cheeseshop:

sudo pip install nose-notify

I don't know if there is a notification plugin for KDE. If you do, let me know and I'll add it here!

Putting it all together

Open a terminal window and cd to the root directory of your project (tdaemon recursively looks at everything down from there).

If you're on OS X, type:

tdaemon --custom-args="--with-growl"

If you're on Linux, type:

tdaemon --custom-args="--with-notify --no-start-message"

Since you're passing custom arguments to nosetests, tdaemon will ask you to confirm that this is the command you want to run. Simply type "y".

Note that, on Linux, nose-notify has a "--no-start-message" option. This is handy, as the start message is mostly useless, and, on Ubuntu, it sticks for a few seconds and delays the actual test results.

Now you can create a file called, say, "tests.py", add tests to it and watch what happens as you save it!

tdaemon-red

tdaemon-green

 

Summary

Install nose and tdaemon:

sudo pip install nose tdaemon

On Mac OS X, install NoseGrowl:

hg clone http://bitbucket.org/osantana/nosegrowl
cd nosegrowl/nose-growl
sudo python setup.py install

and run as:

tdaemon --custom-args="--with-growl"

On Linux, install nose-notify:

sudo pip install nose-notify

and run as:

tdaemon --custom-args="--with-notify --no-start-message"

That's it. Happy coding!

comments Comments