目の前に僕らの道がある

勉強会とか、技術的にはまったことのメモ

テスト駆動開発入門をPythonで写経してみた。10

10章のソースコードがどこを探しても見つからなかったので、やり直しました。その際、前回から気になっていた場所も修正しました。

10章で実施したこと

  • __mul__()メソッドをMoneyクラスに移動
  • デバッグ用の__str__()メソッドの定義

JavaでいうtoString()メソッドにあたるのものは__str__()メソッドと__repr__()メソッドとなります。

str()関数やprint文で使用されるクラスの文字列表現としては__str__()メソッドのようです。ただし、スタックトレースで表示される文字列は__repr__()メソッドを使用しているようです。そこで__str__()メソッドを定義し、__repr__()メソッドに代入するようにしています。__unicode__()メソッドは別に無くてもいいかと思いましたが念のため。

本筋とは関係ないが実施したこと

  • times()メソッドを__mul__()メソッドに置き換え *演算子を使用するよう修正

money.py

#!/usr/bin/env python
# coding: utf-8
"""テスト駆動開発入門 10章 興味深い時(times)
"""

class Money(object):
    def __init__(self, amount, currency):
        self._amount = amount
        self._currency = currency

    def __mul__(self, multiplier):
        return Money(self._amount * multiplier, self.currency())

    @staticmethod
    def dollar(amount):
        return Dollar(amount, "USD")

    @staticmethod
    def franc(amount):
        return Franc(amount, "CHF")

    def currency(self):
        return self._currency

    def __eq__(self, other):
        return self._amount == other._amount and \
                self.currency() == other.currency()

    def __str__(self):
        """デバッグ用出力文字列 原書のtoString()メソッド
        """
        return str(self._amount) + " " + str(self._currency)

    __unicode__ = __str__
    __repr__ = __str__

class Dollar(Money):
    pass

class Franc(Money):
    pass

money_test.py

#!/usr/bin/env python
# coding: utf-8
"""テスト駆動開発入門 10章 興味深い時(times)
"""

import unittest
from money import *

class TestMoney(unittest.TestCase):
    """moneyモジュールのテスト
    """

    def testMultiplication(self):
        """かけ算のテスト
        """
        five = Money.dollar(5)
        self.assertEqual(Money.dollar(10), five * 2)
        self.assertEqual(Money.dollar(15), five * 3)

    def testFrancMultiplication(self):
        """Francクラスのかけ算のテスト
        """

        five = Money.franc(5)
        self.assertEqual(Money.franc(10), five * 2)
        self.assertEqual(Money.franc(15), five * 3)

    def testEuality(self):
        """同値テスト
        """

        self.assert_(    Money.dollar(5) == Money.dollar(5) )
        self.assert_(not Money.dollar(5) == Money.dollar(6) )
        self.assert_(    Money.franc(5)  == Money.franc(5) )
        self.assert_(not Money.franc(5)  == Money.franc(6) )
        self.assert_(not Money.franc(5)  == Money.dollar(5) )

    def testCurrency(self):
        """通貨単位のテスト
        """

        self.assertEqual("USD", Money.dollar(1).currency() )
        self.assertEqual("CHF", Money.franc(1).currency() )


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