Pythonにも3.3からモックモジュールが追加されました。
unittest.mockといいます。今回はこのモジュールの簡単な使い方を紹介します。
モックが必要になる場面として、システム日付の取得があります。
例えば、当日が閏日かどうか判定する関数を考えてみましょう。
なにも考えずに関数を実装すると、次のようになると思います。
def is_leap(): d = datetime.date.today() if 2 == d.month and 29 == d.day: print(str(d) + ' is LEAP') return True else: print(str(d) + ' is NOT LEAP') return False
このままではOSの時計を設定しないと試験ができないので、
日付をパラメータとして渡すようにします。
日付をパラメータとして渡すようにします。
def is_leap(d): if 2 == d.month and 29 == d.day: print(str(d) + ' is LEAP') return True else: print(str(d) + ' is NOT LEAP') return False
日付を注入できるようにしたことで、テストしやすくなりました。
例えば、このようにします。
例えば、このようにします。
assert True == is_leap(datetime.date(2012, 2, 29)) assert False == is_leap(datetime.date(2012, 3, 1))
unittest.mockを使うと、次のような感じになります。
d = unittest.mock.MagicMock() d.month = 2 d.day = 29 assert True == is_leap(d)
モックを使わないほうが単純です。こういう場合はdateオブジェクトを使ったほうがいいでしょう。
さて、現実には全てのコードを自由に変更できるとは限りません。
たとえそんな場合でも、unittest.mock.patchを呼ぶことで、対応できる場合があります。
is_leap関数を修正せずに次のようにします。
さて、現実には全てのコードを自由に変更できるとは限りません。
たとえそんな場合でも、unittest.mock.patchを呼ぶことで、対応できる場合があります。
is_leap関数を修正せずに次のようにします。
with unittest.mock.patch('datetime.date') as dt: dt.today().month = 2 dt.today().day = 29 assert True == is_leap()
datetime.date.today()メソッドが返すオブジェクトをモックオブジェクトと置き換え、
属性を設定することでテストをパスしています。
確かにこの方法でも試験はできますが、日付をパラメータ化するほうがベターだと思います。
他にも、unittest.mockにはメソッドの呼び出しを記録する機能もあります。
詳しいことはオフィシャルのドキュメントを参照してください。
属性を設定することでテストをパスしています。
確かにこの方法でも試験はできますが、日付をパラメータ化するほうがベターだと思います。
他にも、unittest.mockにはメソッドの呼び出しを記録する機能もあります。
詳しいことはオフィシャルのドキュメントを参照してください。
参考:
0 件のコメント:
コメントを投稿