このチュートリアルを実際に試すには、なにはともあれ Modipyd をインストールしなくてはいけません。インストールの手順についてはModipyd のインストールが参考になるはずです。
これから、ふたつの簡単な Python スクリプトを例に、Modipyd の自動テストツールの使い方を説明していきます。:
[~/modipyd/examples/widget]
% ls
test_widget.py widget.py
widget.py は Widget クラスを含む Python スクリプトです。一方、test_widget.py はテストケースになります。
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()
pyautotest を実行すると、これらの Python ファイルの更新を監視するようになります(-v/--verbose オプションを指定すると、プログラムの処理経過が分かるようになるので便利です):
% 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']
最後の出力が示しているように、pyautotest は widget.py と test_widget.py の監視を開始しています。
ここで widget.py を見てみましょう。Widget.__init__() では 3 つある引数をそれぞれ、インスタンス変数に代入していますね。Python ではタプルを使うことで、複数の代入文をひとつにまとめることができます。それでは、widget.py をそのように編集します。
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)
widget.py を編集すると、pyautotest は自動的に、変更されたファイル(個の場合 widget.py)を読み込み、関連するテストケースをすべて実行します(この場合 test_widget.py)。
Note
関連するテストケースを特定するとき、pyautotest はファイル名のパターンを使用しません。 そのため、テストケースのファイル名は widget_test.py、WidgetTest.py、 test/widget.py など、自由につけることができます。
[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
Widget クラスには足りない機能がたくさんあります。この節では resize() メソッドを追加しましょう。:func:resize メソッドはふたつの引数 width と height をとり、自身の大きさを変更します。テスト駆動開発の精神にのっとり、Widget.resize() を実装するまえにテストケースを書いていきます。
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()
新しいテストケースとして WidgetResizeTestCase を追加しました。まだ Widget.resize() がないので、このテストは失敗するはずです。
Note
pyautotest は新しく追加された unittest.TestCase のサブクラスを 自動的に検出します。
======================================================================
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
予想通り、テストは失敗しました。それでは、Widget.resize() を実装しましょう。
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
この変更を保存すると、pyautotest が自動でテストケースを実行し、そのテストは成功します。
[INFO] Running UnitTests: test_widget
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK