Saturday, March 18, 2006

Nose 0.9: good ideas

Thanks to Mika Eloranta, nose 0.9 will feature a plugin that allows selection of tests to run by introspection of test class, method or function attributes. Here are a few usage examples:

  • Simple syntax (-a, --attr) examples:
    • nosetests -a status=stable
      Only test cases with attribute "status" having value "stable"
    • nosetests -a priority=2,status=stable
      Both attributes must match
    • nosetests -a tags=http
      Attribute list "tags" must contain value "http"
    • nosetests -a slow
      Attribute "slow" must be defined and its value cannot be equal to False (False, [], "", etc...)
    • nosetests -a !slow
      Attribute "slow" must NOT be defined or its value must be equal to False
  • Eval expression syntax (-A, --eval-attr) examples:
    • nosetests -A "not slow"
    • nosetests -A "(priority < 5) and not slow"
    • Quoted expression will be evaluated in the context of each test case, and only test cases where it evaluates to true will be selected.

Pretty cool. This is such a good idea, and will be so generally useful, that I think it alone justifies the pluginization of nose. I'm excited to see what other good ideas might be lurking out there, too.

Wednesday, March 08, 2006

Nose 0.9: svn and trac available

Thanks to the great folks at Python Hosting, nose is now available via svn checkout, and has a trac instance for documentation, bug reports and feature requests. Here's trac: http://nose.python-hosting.com.

A note of caution: the trac instance and svn access are meant to support the development of the next nose version, 0.9. 0.9 is under heavy development right now, so the code available on the side and the documentation in trac is likely to be broken, wrong, and out of date all at the same time.

Saturday, March 04, 2006

Nose 0.9: output capture

Or, monkeypatches in rear view mirror may be larger than they appear.

Nose runs in two environments: one where it has control over the entire test-running and output process, and another where it has direct control only over the tests collected. Handling output capture and printing captured output with errors and failures is easy in the first case. In the second, it requires a monkeypatch: something somewhere that's not part of nose needs a piece of nose inserted, to handle capturing and printing the output capture.

In cases like these, the best strategy is to pick the smallest monkey and patch as gently as possible. I know this. So the only explanation I can come up with for the decision I made in the current release of nose to patch the builtin Exception class -- yes, the base class for all exceptions everywhere -- instead of, say, unittest._TextTestRunner, is that an optical illusion more powerful than 10,000 of those annoying 3d posters from the 1990s made the biggest monkey in the world look like some sort of 1/72nd scale anorexic marmoset figurine.

Nose 0.9 will correct this insanity by only patching unittest, and only when necessary. As a happy side effect, this also allows nose to lose three now-superfluous classes and a bunch of confusing documentation.

Thursday, March 02, 2006

Nose: the road to 0.9

Nose, my little python test runner, has set foot (or, Simpson-philes, shopping cart wheel) on its mystical journey to version 0.9. Since it's gotten a bit more use and attention lately, I'm going to chronicle major changes in operation and APIs as I make them here, on this dusty old blog. First up, test selection via the command line. After too much mulling, I've decided that Titus Brown is right, and this: nosetests a.module Should discover all tests, but run only the test(s) specifed. To select a single test or test class, with nose 0.9, you'll be able to say: nosetests a.module:Class.method other.module:function I think that will be an improvement. The -f, -m and -o options will most likely be deprecated.