PyBlosxom Recent Posts Plugin
04 Jun 2008 19:22
I’ve been using PyBlosxom to run this blog and, increasingly, the static content of the site.
PyBlosxom tries to do as little as possible in the core, saving most features for its plugin framework. Nice technically, but leaving features up to “the community” to implement sometimes leaves some frustrating holes, as I discovered when I searched in vain for a plugin to implement “recent posts” functionality.
The upside is that it was really easy to implement—about 100 lines of Python. It’s available from the software page if you want to run it yourself; if you have any questions about it, feel free to contact me. about it.
Update: I posted about my plugin to pyblosxom-devel and they added it to the plugins list. w00t, as the kids say. If you’re coming here looking for more information on the plugin, I suggest you read the docstring comments of the plugin itself.
Category: geekery/python
Python Decorators and Unit Tests
15 Aug 2006 21:46
Here’s one thing that’s always bugged me about Python’s unittest module. Consider the following:
class MyTest(unittest.TestCase):
def setUp(self):
self.x = foo()
self.y = bar()
def tearDown(self):
del self.x
del self.y
def test_something(self):
"Run a test here."
# The only way I can get hold
# of any state initialized in
# startUp() is via my self reference.
# So...
self.assertEqual(self.x, self.y)
It’s a little bit annoying to have to refer to x and y as self.x and self.y. In a more perfect world, x and y could be passed into the test as function arguments.
Enter Python 2.4 and the new (and unfortunately-named) decorator syntax. (It has nothing to do with the GoF pattern of the same name.) I was learning a lot about this new language feature for another project, and while writing tests for it, it occurred to me that I could use decorators to put this little annoyance behind me:
def test_a(fn):
def wrapped(self):
fn(foo(), bar())
# The following is good form to make the
# decoration as transparent as possible:
wrapped.__name__ = fn.__name__
wrapped.__doc__ = fn.__doc__
wrapped.__dict__ = fn.__dict__
return wrapped
class MyTest(unittest.TestCase):
@test_a
def test_something(self, x, y):
"Run a test here."
# Yay! Clarity!
self.assertEqual(x, y)
To me, that’s really clear. As a bonus, you don’t need to explicitly un-define the variables you create during setup—although you can finalize them however you need to in the wrapped function defined by the decorator.
But wait, there’s more! Another thing that irritates me about unittest (and JUnit, for that matter, but I haven’t written any Java in forever) is that you get as many test methods as you want per class, but only one pair of setup and teardown methods. Want to set up a test a different way? Either do it in the test method, or make a whole new class. That can get annoying:
def test_a(fn):
def wrapped(self):
fn(foo(), bar())
# The following is good form to make the
# decoration as transparent as possible:
wrapped.__name__ = fn.__name__
wrapped.__doc__ = fn.__doc__
wrapped.__dict__ = fn.__dict__
return wrapped
class BaseTest(unittest.TestCase):
"""Superfluous base class to hold
some utility methods."""
def assert_squared(self, x, y):
self.assertEquals(x*x, y)
class MyTest(BaseTest):
"Tests set up a certain way."
def setUp(self):
self.x = foo()
self.y = bar()
def tearDown(self):
del self.x
del self.y
def test_something(self):
"Run a test here."
self.assert_squared(self.x, self.y)
class MyOtherTest(BaseTest):
"Tests set up a certain way."
def setUp(self):
self.x = foo()
self.y = bar() + 1
def tearDown(self):
del self.x
del self.y
def test_something_else(self):
"Run a test here."
self.assert_squared(self.x, self.y)
So much redundant code, so little point. But with decorators, this can get a whole lot cleaner:
def bless(wrapped, fn):
"Do some decorator bureaucracy."
wrapped.__name__ = fn.__name__
wrapped.__doc__ = fn.__doc__
wrapped.__dict__ = fn.__dict__
return wrapped
def test_a(fn):
def wrapped(self):
fn(foo(), bar())
return bless(wrapped, fn)
def test_b(fn):
def wrapped(self):
fn(foo(), bar() + 1)
return bless(wrapped, fn)
class MyTest(unittest.TestCase):
"A blissfully clear test class."
# Because I can keep everything on one class,
# there's no need for a base class to hold this.
def assert_squared(self, x, y):
self.assertEquals(x*x, y)
@test_a
def test_something(self, x, y):
"Run a test here."
self.assert_squared(x, y)
@test_b
def test_something(self, x, y):
"Run another test here."
self.assert_squared(x, y)
(Hmm, I can’t ever seem to make all my tests pass at the same time….)
There are some rough edges to this trick. To get the same semantics as setUp and tearDown, you have to write your decorator with a try/finally block like this:
def test_a(fn):
def wrapped(self):
a, b = do_setup()
try:
fn(a, b)
finally:
do_teardown(a, b)
return bless(wrapped, fn)
Furthermore, decorators can take arguments, and get considerably more complex when they do. (I’ll save my bitchfest about that for a later post.) For me, though, the benefits are significantly outweighing the costs.
Please feel free to share any caveats to this approach, or experiences making Python unit tests clearer and easier to write.
Category: geekery/python
Copyright © 2006-2008 Phil Groce. All Rights Reserved.