minimockを使う、という話

あまり詳しいことはわかっていない

詳細はpypiの公式ドキュメント( MiniMock 1.2.8 : Python Package Index ) かminimockの使い方 - 今川館 を参考にしてください

自分なりの理解

モックはテストをする上でダミーとして差し替えるもの。もちろん本物のデータやfixtureが使えるに越したことはないが、なんらかの事情で(他の会社と協力して開発し地ているため、先行的に実装しているとか、URLリクエストを頻繁に行いたくないとか)そういうときにダミーとして差し替える→モックを使うということになる。詳しい概念はググってください。なんかまあ、よく携帯ショップの携帯のダミー端末のことをモック機というらしいのでそういうものだと信じている。

minimockを使う

詳しい使い方やドキュメントはさっき行ったとおり上記のを参考にしてください

mockをあてる

なにはなくとも、ある関数をmock関数でモックにしてしまう

#ちなみにDjango前提だが、これはManagerがなんとかいって動かない
mock("Model.objects.all", returns=[])

これはあるModelを空にするという処理 Model.objects.all().delete() をしたいが、それを行うとテストデーター自体に影響を与えてしまうためモックに差し替えるという話だ。今回は Model.objects.all() を呼んだ時に returnsの[] がかえってくる、というダミー処理として代行させている。

mockをあてるその2

あるHogeAPIがあるとする。

class HogeAPI(object):
   #__getattr__を定義、funcを引数に取る
   def __getattr__(self, func):
       #innerで**kwをうけとってよしなにする
       def _internal(**kwargs):
           if func == 'hoge':
               return "hoge process. No." + str(kwargs.get('No'))
           else:
              raise AttributeError('cannot find this attribute. "%s"' % func )
       return _internal

#HogeAPI().hoge(No=1) # => hoge process. No.1
#HogeAPI().fuga(No=1) # => raise AttributeError: cannot find this attribute. "fuga"

あるclassに対して__getattr__でfuncを受け取り、インナーで**kwを受け取る。**kwで受け取ったものをよしなにして処理する。というものがあるとする。

mock("HogeAPI.__getattr__", returns=lambda x: dict(x=x))

あるclassのプロパティが存在しないとき(HogeAPI.getMoge()などが関数定義ではなく__getattr__経由で定義されている)に__getattr__をつかって返させることがある。おれも詳しくないからググれ。そのときは__getattr__自体をmock化してしまい、かえってくるこの場合は関数をlambdaで包んで返してやる。ちなみにlambdaの引数(この場合はx)とあるが、てきとうではだめで、差し替えてあるそのものの引数を使わなくてはならない

__getattr__について

1. __getattr__ 呼ばれる
2. post_funcという関数がかえされる
3. ()が付いていれば関数として実行される
という流れです。デコレータとはまたちょっと違うイメージですが。__getattr__ という特殊変数はクラスに「存在しない属性」が呼ばれた時に、実行される関数なのです。
@xxxxxxxxx

あと__getattr__についてはりとる(@little__five)の解説がほぉってなった。蟹は金、海老は銀

__getattr__をつかったときの処理の流れについて

1. HogeAPI().getMoge(**dict(No=no)) を呼び出す
2. getMogeは存在しないので__getattr__が呼ばれる
3. __getattr__ は mock化されているので、lambda x: x という関数を返す
4. 帰って来た lambda x: x 対して 1では (**dict(No=no)) という引数を渡して関数を実行しようとする。
5. lambda x: という関数は、Noという引数を受け取る定義じゃないのでさっきのエラーがでる
という順番かな
@xxxxxxxxxx

演算子のオーバーロードは知ってても使い方も読み方もよくわからなかったよ!ウワワアアアン