「テスト駆動開発」をPythonで書き直してみた 5
書籍「テスト駆動開発」をPythonで書き直してみたシリーズの5です。前回は、DollarクラスとFrancクラスの親クラスとしてMoneyクラスを作り、重複したコードを親クラスへ引き上げました。
pyhaya.hatenablog.com
- 作者: Kent Beck,和田卓人
- 出版社/メーカー: オーム社
- 発売日: 2017/10/14
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
DollarクラスとFrancクラスを消す
テストでDollar、Francを使わないようにする
DollarクラスとFrancクラスを消すために、まずはテストコードからこれらのクラスを使っている部分をなくしていきます。
tests/test_money
import sys sys.path.append('../src') import unittest from money import Money class MoneyTest(unittest.TestCase): 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): five = Money.franc(5) self.assertEqual(Money.franc(10), five.times(2)) self.assertEqual(Money.franc(15), five.times(3)) def testEquality(self): self.assertNotEqual(Money.franc(5), Money.dollar(5)) if __name__ == '__main__': unittest.main()
Moneyクラスを経由してDollarクラスとFrancクラスを読み込みます。
Moneyクラスを書き直す
ではテストが通るようにMoneyクラスを書き換えます。だんだんインポートが面倒になってきたのでDollarクラスとFrancクラスをmoney.pyに移してきます。
src/money.py
class Money: def __init__(self, amount, currency): self.amount = amount self.currency = currency def __eq__(self, other): return self.__dict__ == other.__dict__ @staticmethod def dollar(amount): return Dollar(amount) @staticmethod def franc(amount): return Franc(amount) class Franc(Money): def __init__(self, amount, currency='CHF'): super().__init__(amount, currency) def times(self, multiplier): return Franc(self.amount * multiplier) class Dollar(Money): def __init__(self, amount, currency='USD'): super().__init__(amount, currency) def times(self, multiplier): return Dollar(self.amount * multiplier)
Moneyクラスに吸収する
ここまでくれば、FrancクラスとDollarクラスの削除まではもう一歩です。これらのクラスの違いはcurrency
フィールドの違いだけなので、次のようにしてやれば統合できそうです。
class Money: def __init__(self, amount, currency): self.amount = amount self.currency = currency #追加 def __eq__(self, other): return self.__dict__ == other.__dict__ @staticmethod def dollar(amount): return Money(amount, 'USD') @staticmethod def franc(amount): return Money(amount, 'CHF') def times(self, multiplier): return Money(self.amount * multiplier, self.currency)
これで、DollarとFrancクラスの統合は完了です。最後にテストを走らせて成功するのを確認します。