「テスト駆動開発」をPythonで書き直してみた 2
前回の記事の続きです。「テスト駆動開発」の多国通貨をPythonで実装します。
pyhaya.hatenablog.com
[asin:4274217884:detail]
目次
等価性を定義する
前回の記事では、通貨の計算として掛け算を実装しました。今回は等価性、つまり通貨として価値が等しいかどうかを判別できるようにします。まずはテストから書きましょう。
tests/test_money.py
import sys sys.path.append('../src') import unittest from dollar import Dollar class MoneyTest(unittest.TestCase): def testMultiplication(self): five = Dollar(5) product = five.times(2) self.assertEqual(10, product.amount) product = five.times(3) self.assertEqual(15, product.amount) def testEquality(self): self.assertTrue(Dollar(5).equals(Dollar(5))) if __name__ == '__main__': unittest.main()
この状態でテストを実行するとエラーになります。では実装に取り組みましょう。
src/dollar.py
class Dollar: def __init__(self, amount): self.amount = amount def times(self, multiplier): return Dollar(self.amount * multiplier) def equals(self, money): return True
まずは明確な実装。ただTrue
を返すだけ。では、テストコードにもう一つテストを付け加えます。
tests/test_money.py
import sys sys.path.append('../src') import unittest from dollar import Dollar class MoneyTest(unittest.TestCase): def testMultiplication(self): five = Dollar(5) product = five.times(2) self.assertEqual(10, product.amount) product = five.times(3) self.assertEqual(15, product.amount) def testEquality(self): self.assertTrue(Dollar(5).equals(Dollar(5))) self.assertFalse(Dollar(5).equals(Dollar(6))) if __name__ == '__main__': unittest.main()
このようにテストを書くと、equals
メソッドは各Dollarオブジェクトのamount
フィールドを比較して等価性を判断していることに気づく。すると下のようなコードが書ける。
src/dollar.py
class Dollar: def __init__(self, amount): self.amount = amount def times(self, multiplier): return Dollar(self.amount * multiplier) def equals(self, money): return self.amount == money.amount
これで等価性が実装できた。
Javaとの比較
ここまでくると、Javaで書かれた「テスト駆動開発」のコードとは差が出始めます。このequals
メソッドはJavaでは下のように書かれています。
public boolean equals(Object object){ Dollar dollar = (Dollar) object #キャスト return amount == dollar.amount; }
このコードとPythonのコードを比較した場合に一番大きな違いは2行目です。JavaではPythonとは異なりクラスキャストによってオブジェクトのクラスを変更することができます。
現時点では、Pythonでキャストができないことで不利益は出ていないので放置します。
まとめ
- 通貨の等価性を確かめるコードを追加した
- Pythonにキャストがないのは現時点では問題にならないので無視した
ソースコードはGit Hubにあります。記事ごとにコミットしているので、part2のところにチェックアウトすればこの段階のコードがわかります。
github.com