Test so you have less code to test
More than one year ago, Danilo Sato and I started a pet project to practice TDD. We ended up not making all that much progress so far, codewise (over one year! So much for "agile"...), but it's been a great learning exercise. It's a Python test-driven implementation of the Stratego game, and Danilo has documented our early programming sessions on his blog (in Portuguese, I'm waiting for him to catch up to start bitching for an English translation, but I'll post stuff about it here as well). We've recently resumed work on it and it should show up both here and at Danilo's.
Anyway, I have since developed a taste for testing (a "teste", you could say) and, when I started cleaning up nnebs, I found myself writing tests for everything as I went through the code (no, it had no tests before; yes, it was my graduation project; anyone can have a Comp. Sci. B.Sc. these days...). Doctests, even, but more on that later.
One thing that struck me as interesting, in this process, came up while I was writing tests for some state-related classes. Nnebs is basically a spam filter, and I had decided its classifiers (as well as a few other classes) should be stateful, that is, they should be able to easily represent a particular configuration and switch back to it when requested. Since a few different classes would be stateful, I created a Stateful class from which classes wishing to be stateful should inherit. So far, so good. All these classes needed to do was inherit from Stateful and define which attributes would make up their states.
To describe a state itself, I created another class (aptly named "State") to hold attributes and their default values. It defined methods to add, delete, set and query attributes. It also defined that two state objects would be equal if their attributes and values were the same.
The State class was about 30 lines of code and worked quite well. However, while writing its tests I noticed they seemed a bit too trivial, which struck me as odd. I was having to write tests like
>>> State(attr1=val1, attr2=val2) == State(attr1=val1, attr2=val2)
True
>>> State(attr1=val1).get('attr1')
val1
That just doesn't seem right :)
I figured I could delegate some of State's behaviour by making it a subclass of "dict". Great, there goes my "get" implementation. And my equality implementation. And my __del__ implementation. And my initialization implementation. And, well, I assume you can take it from here.
So State is now simply a dict. Running the tests confirmed that everything worked as before. My code is 30 lines of bug-food (a.k.a. "code") shorter. And I'm a lot happier with nnebs and more confident in its code.