2010年10月19日火曜日

PythonでTDDしてみた

Python以外の言語でTDDをした経験がある訳ではないので、あちこちのページを参考にしながらかなり適当にやってみた。
とりあえず試しに書いたコードは、
from weakref import WeakValueDictionary

class NicoChannel:
    _InstancePool = WeakValueDictionary()

    def __new__(cls, channelid):
        try:
            channelid = int(channelid)
        except ValueError:
            return None

        if channelid < 1:
            return None

        obj = NicoChannel._InstancePool.get(channelid, None)
        if not obj:
            obj = object.__new__(cls)
            NicoChannel._InstancePool[channelid] = obj

        return obj

    def __init__(self, channelid):
        self.channelid = int(channelid)

    def __str__(self):
        return str(self.channelid)
で、テストの方はこんな感じに。
#!/usr/bin/env python3.1
import unittest
from nicochannel import NicoChannel

class TestNicoChannel(unittest.TestCase):
    def setUp(self):
        pass

    def tearDown(self):
        pass

    def testNewClass(self):
        self.assertNotEqual(NicoChannel(1), None)

        channel1 = NicoChannel(1)
        self.assertEqual(str(channel1), '1')

        channel2 = NicoChannel(2)
        self.assertEqual(str(channel2), '2')

        # Test for Flyweight pattern.
        channel1_clone = NicoChannel(1)
        self.assertEqual(channel1, channel1_clone)

        self.assertNotEqual(channel1, channel2)

        # If channelid isn't a number, NicoChannel(channelid) is None
        self.assertEqual(NicoChannel('A'), None)

        # If channelid is a negative number, NicoChannel(channelid) is None
        self.assertEqual(NicoChannel(-1), None)

        # If channelid is a zero, NicoChannel(channelid) is None
        self.assertEqual(NicoChannel(0), None)

        # If channelid is a number string, NicoChannel(channelid) isn't None
        channelzerotwo = NicoChannel("02")
        self.assertNotEqual(channelzerotwo, None)

        # Testing normalization of channelid.
        self.assertEqual(str(channelzerotwo), '2')

        # Test NicoChannel("02") == NicoChannel(2)
        self.assertEqual(channelzerotwo, channel2)



class TestRandom(unittest.TestCase):
    pass

if __name__ == '__main__':
    unittest.main()

現時点でよく分からなかったのは、
  • レッドからグリーンになったらcommitするのが一般的なパターンのようだけど、テストを追加してレッドになった時点ではcommitしない方がいい?(使ってるSCMはMercurial)
  • 前回のサイクルで追加したコードのせいで、これから追加しても即グリーンになるのが分かってるようなテストは追加しない方がいい?
  • Flyweightパターンにする時に一気に10行ぐらい追加するのってマズい?
etc...。
この辺りは初歩的な疑問のはずなので、ちゃんとした書籍を一冊買えば即解消しそうな予感。

0 件のコメント:

コメントを投稿