20181103 ミニTDDBC振り返りその2
の続きです。
今回学んだことは
1. きれいなコミットメッセージの書き方
2. 学習テスト
3. DDDなリファクタリング
この記事では、「2. 学習テスト」について書きます。
今回の題材はこちら
我々のGitHub
2. 学習テスト
問2で、等しいバージョンナンバーから成るSemVerオブジェクトが等しく、異なるバージョンナンバーから成るSemBerオブジェクトが異なるといった実装をしました。
テストコード↓
class TestSemVer(unittest.TestCase): def test_同じバージョンを持つ2つのオブジェクトが等しいことを確認(self): self.assertTrue(SemVer(1, 4, 2) == SemVer(1, 4, 2)) def test_違うバージョンを持つ2つのオブジェクトは等しくないことを確認(self): self.assertFalse(SemVer(1, 4, 2) == SemVer(2, 30, 400))
このテストを書いた時点のプロダクトコード↓
class SemVer: def get_notation(self) -> str: return str(self.major) + "." + str(self.minor) + "." + str(self.patch) def __eq__(self, other: SemVer) -> bool: return True
eqを実装しよう、ということでまず最初の変更↓
def __eq__(self, other) -> bool: return self.get_notation() == other.get_notation()
しかしこれだと、別クラスのインスタンスであっても、文字列が等しければ等しいとなってしまいます。
ということで、isinstanceを利用しようという話になりました。
しかし、私はisinstanceを利用するのが初めてで使い方がわかりませんでした(^^;
ここで、学習テストの出番です。
学習テストとは、APIや言語の仕様が期待通りに動くかを確認するためのテストです。
ここでは、 isinstanceの引数を色々いれてみて、どのように動くか確かめました。
学習テストのテストコード↓
def test_isinstanceの勉強(self): # 学習テスト self.assertFalse(isinstance('hoge', SemVer)) # 1 self.assertTrue(isinstance('hoge', str)) # 2
1つ目のテストでは、strオブジェクト'hoge'がSemVerオブジェクトでないかを判定しています。
2つ目のテストでは、strオブジェクト'hoge'がstrオブジェクトであるかを判定しています。
2つともPassしました。
2つのテストから、
1. isinstanceでは、第一引数は判定対象となるオブジェクトであり、第二引数はクラス名を入れる仕様である
2. isinstaceは、第一引数のオブジェクトが第二引数のクラスのインスタンスかを判定するメソッドである
ということが分かりました。
実際に1と2の通りに動くか、確認します。
self.assertTrue(isinstance(SemVer(1, 4, 2), SemVer))
Passしました。
仕様が分かったところで、プロダクトコードを変更します。
def __eq__(self, other) -> bool: return self.get_notation() == other.get_notation() \ and isinstance(other, SemVer)
これで、同じバージョンナンバーであり、かつSemVerオブジェクトであれば等しいという実装ができました。
学習テストは、その場ですぐに仕様を確認することが出来るのでとても便利だと思いました!
ドキュメント読んでも理解が曖昧な時に積極的に利用していこうと思います(^^)
isinstanceについてのドキュメント↓