So after some experiments in C++, this week I got back to where I once started: Python! The idea was, that I'd produce a quick prototype for something, so that I could translate it into another language. However, I got distracted as I often do.
First of all, I wanted to be able to test things in my prototype, so I wanted some kind of unit testing, so instead of actually starting to write code, I headed for the intertubes and googled for unit testing in Python.
In fact, there is the standard module unittest
, just here. That's really cool, I thought, I'd be looking for hours to find something (as I did with C++), but this way, I could just begin. What I found rather annoying was that you normally have to put
in front of your test method names. My free spirit rebelled against such puny laws - you gotta start small with rebelling, right? Anyway, there was of course the alternative to write a test suite and just manually add all my test methods. Well... no.test
But on the other hand, whenever you get an API to do something, you might as well automate the something as good as you can, so I started with the familiar JUnit syntax @Test
to annotate test methods.
For those, who know the more obscure features of python, it should be clear, that this is a decoration in Python - a function modifying functions. In this case, I just left a note for me in the func_dict
:
def Test(f):
f.func_dict["Test"] = True
return f
On the other hand, there was the problem, that no one would care for this fancy note, so I wrote an
InSuite
decorator for TestCase classes.class InSuite(object):
def __init__(self,testsuite):
if testsuite not in __TESTSUITES__:
__TESTSUITES__.append(testsuite)
self.test = testsuite
def __call__(self,f):
for i in f.__dict__:
if self.isTest(f.__dict__[i]):
self.test.addTest(f(i))
return f
def isTest(self,x):
try:
return x.Test
except AttributeError:
return False
This would add each annotated method to the given TestSuite
, and all TestSuite
s that are somewhere mentioned, to a global list. These two decorators are a great team, just take a look at my tests:
FunctorTestSuite = unittest.TestSuite()
@InSuite(FunctorTestSuite)
class FunctorTestCase(unittest.TestCase):
def setUp(self):
...
@Test
def shouldSquareResult(self):
...
@Test
def shouldNotTakeTooMuchArguments(self):
...
Tada! No more worries about naming conventions and InSuite could easily be extended to check for other annotations as well. Splendid, that was a rather useful waste of time!
No comments:
Post a Comment