I'm a freak about unit tests. In fact I often enjoy writing the tests more than I enjoy writing the actual production code. Seven years ago when first learning about unit tests in my day job (coding in perl with a home grown test framework). I decided to experiment with them in python. Starting with the built in
unit test framework, I quickly found that I didn't like it. It didn't work the way I thought it should work and for me, made testing more difficult than it should be. I went in search of something that worked more like I do.
That search led to Codespeak's
py.test. It works the way I do, no setup required, no test frameworks required, no big fixtures to build up or tear down. Write a test...
In the file
test_my_module.py
import my_module
def test_my_function():
assert my_module.my_function() == 42
In the file
my_module.py
def my_function():
return 42
I can now run
py.test
and it will find my test and run it for me reporting any errors.
As I started using PubSub, I ran into some new test issues for me, just how do you effectively test that messages were being sent or received when you believed they should be. I tinkered with it for a while, and eventually came up with the following template for my tests...
def test__Character__generates_pubsub_message_on_attribute_set(self):
def got_message(message):
self.got_pubsub_message = True
self.message = message
self.got_pubsub_message = False
Publisher().subscribe(got_message,
'Character.update.name')
self.c.name = 'New Name'
assert self.c.name == 'New Name'
assert self.got_pubsub_message
assert self.message.data == 'New Name'
self.got_pubsub_message = False
Publisher().subscribe(got_message,
'Character.update.abilities')
self.c.abilities = {'STR':10, 'DEX':11, 'CON':12,
'INT':13, 'WIS':14, 'CHA':15}
assert self.got_pubsub_message
assert self.message.data == \
{'STR':10, 'DEX':11, 'CON':12,
'INT':13, 'WIS':14, 'CHA':15}
This test method is part of a test class that handles all the setup and teardown functionality, setting the initial state for each one of the test methods in the class.
One question you might ask about the above is why do I assert that attribute set on line 10 has the correct value on line 11. I do it because MsgObject doesn't just set the attribute, it does other things and since it does other things, it is quite likely that at some point in my code's life I will accidentally delete the line that actually sets the attribute, and I'd like to have my tests fail if I do so.