pyhaya’s diary

プログラミング、特にPythonについての記事を書きます。Djangoや機械学習などホットな話題をわかりやすく説明していきたいと思います。

「テスト駆動開発」を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