9章で実施したこと
- DollarクラスとFrancクラスのコンストラクタを共通化
- 通貨単位を返すcurrency()メソッドの実装
- times()メソッド内でのファクトリメソッドの使用
times()メソッドが気持ち悪いです。Python的には__mul__()メソッドを定義して*演算子をオーバーロードするのが正しいのでしょう。この時点で気がつけばよかったです。この点、後の章で修正しています。
money.py
#!/usr/bin/env python # coding: utf-8 """テスト駆動開発入門 9章 生きている時(times) """ class Money(object): def __init__(self, amount, currency): self._amount = amount self._currency = currency def times(multiplier): raise NotImplementedError @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.__class__ == other.__class__ class Dollar(Money): def times(self, multiplier): return Money.dollar(self._amount * multiplier) class Franc(Money): def times(self, multiplier): return Money.franc(self._amount * multiplier)
money_test.py
#!/usr/bin/env python # coding: utf-8 """テスト駆動開発入門 9章 生きている時(times) """ import unittest from money import * class TestMoney(unittest.TestCase): """moneyモジュールのテスト """ def testMultiplication(self): """かけ算のテスト """ five = Money.dollar(5) self.assertEqual(Money.dollar(10), five.times(2) ) self.assertEqual(Money.dollar(15), five.times(3) ) def testFrancMultiplication(self): """Francクラスのかけ算のテスト """ five = Money.franc(5) self.assertEqual(Money.franc(10), five.times(2) ) self.assertEqual(Money.franc(15), five.times(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()