You can read the How to install Modipyd document, if you don’t install Modipyd yet.
Suppose you have two .py files:
[~/modipyd/examples/widget]
% ls
test_widget.py widget.py
The file named widget.py is a normal Python script. On the other hand, test_widget.py is a test case includes unittest.TestCase subclass.
widget.py:
import os
import sys
class Widget(object):
"""
Widget is a User Interface (UI) component object. A widget
object claims a rectagular region of its content, is responsible
for all drawing within that region.
"""
def __init__(self, name, width=50, height=50):
self.name = name
self.width = width
self.height = height
def size(self):
return (self.width, self.height)
test_widget.py:
import unittest
from widget import Widget
class SimpleWidgetTestCase(unittest.TestCase):
def test_init(self):
widget = Widget('The widget', 10, 10)
self.failUnless(widget.size() == (10, 10),
'incorrect size')
def test_default_size(self):
widget = Widget('The widget')
self.failUnless(widget.size() == (50, 50),
'incorrect default size')
if __name__ == '__main__':
unittest.main()
You can start monitoring changes in these files by executing pyautotest (With -v/--verbose option flag, pyautotest prints detailed information about its operations):
% pyautotest -v
[INFO] Loading plugin: <class 'modipyd.application.plugins.Autotest'>
[INFO] Loading BytecodeProcesser 'modipyd.bytecode.ImportProcessor'
[INFO] Loading BytecodeProcesser 'modipyd.bytecode.ClassDefinitionProcessor'
[INFO] Monitoring:
test_widget: test_widget.py
Dependencies: ['widget']
Reverse: []
widget: widget.py
Dependencies: []
Reverse: ['test_widget']
As output message mentioned above, the pyautotest tool is now monitoring widget.py and test_widget.py.
You have three assignment statements in Widget.__init__(), assigns function arguments to instance variables. You can perform multiple assignment using tuples.
widget.py:
import os
import sys
class Widget(object):
"""
Widget is a User Interface (UI) component object. A widget
object claims a rectagular region of its content, is responsible
for all drawing within that region.
"""
def __init__(self, name, width=50, height=50):
self.name = name
self.width, self.height = width, height
def size(self):
return (self.width, self.height)
When you edit widget.py, pyautotest automatically reloads modified module (widget.py), and then, automatically runs all dependent testcase (test_widget.py).
Note
pyautotest makes no assumptions about filename of test cases, you can have widget_test.py or WidgetTest.py, test/widget.py, ... etc.
[INFO] Reload module descriptor 'widget' at widget.py
[INFO] Modified: widget: widget.py
Dependencies: []
Reverse: ['test_widget']
[INFO] -> Affected: widget
[INFO] -> Affected: test_widget
[INFO] Running UnitTests: test_widget
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
You decide to add Widget.resize() method. The Widget.resize() takes two arguments width and height, then change the region with new rectangle. Along with test driven development, you write a test before the Widget.resize() implementation.
test_widget.py:
import unittest
from widget import Widget
class SimpleWidgetTestCase(unittest.TestCase):
def test_init(self):
widget = Widget('The widget', 10, 10)
self.failUnless(widget.size() == (10, 10),
'incorrect size')
def test_default_size(self):
widget = Widget('The widget')
self.failUnless(widget.size() == (50, 50),
'incorrect default size')
class WidgetResizeTestCase(unittest.TestCase):
def test_resize(self):
widget = Widget('The widget', 15, 30)
self.failUnless(widget.size() == (15, 30))
widget.resize(45, 50)
self.failUnless(widget.size() == (45, 50))
if __name__ == '__main__':
unittest.main()
The test must inevitably fail because Widget.resize() is missing. This validates that the test harness is working correctly and that the test does not mistakenly pass without requiring any new code.
Note
pyautotest automatically finds new unittest.TestCase subclass and its dependencies.
======================================================================
ERROR: test_resize (test_widget.WidgetResizeTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_widget.py", line 21, in test_resize
widget.resize(45, 50)
AttributeError: 'Widget' object has no attribute 'resize'
----------------------------------------------------------------------
Ran 3 tests in 0.001s
So, let’s begin to write Widget.resize() code.
widget.py:
import os
import sys
class Widget(object):
"""
Widget is a User Interface (UI) component object. A widget
object claims a rectagular region of its content, is responsible
for all drawing within that region.
"""
def __init__(self, name, width=50, height=50):
self.name = name
self.resize(width, height)
def size(self):
return (self.width, self.height)
def resize(self, width, height):
self.width, self.height = width, height
Now all test cases pass.
[INFO] Running UnitTests: test_widget
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK