恐怖のMocking
Python と Mock の話。
import されているモジュールをモックに差し替えたいときに
from minimock import Mock
import hoge
hoge.fuga = Mock('hoge.fuga')
と安易にやってはいけない。 これだと restore しても元の hoge.fuga には戻らない。
例えば
turtle.py というのを考える:
# turtle.py
def soup():
return 'turtle'
tests.py も考える。
import unittest
from minimock import Mock, restore
import turtle
class TurtleTest(unittest.TestCase):
def setUp(self):
turtle.soup = Mock('turtle.soup',
returns=u'mock turtle')
def tearDown(self):
restore()
print turtle.soup()
def test_soup(self):
self.assertEqual(turtle.soup(), 'mock turtle')
if __name__ == '__main__':
unittest.main()
と restore までしてやるわけだけど、悲しいことに(あたいまえなことに) turtle.soup はモックのままである。
% python -m tests
Called turtle.soup()
Called turtle.soup()
mock turtle
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
よくやるのがテスト対象のモジュール target に対して、そこで import されている turtle.soup を差し替えるというもの。 target.turtle.soup をモックに差し替えるんだろうけど、その場合も元に戻っていないと厄介。
mock 使おう
Mock 使わずに mock 使えばいい。
from minimock import mock, restore
...
class TurtleTest(unittest.TestCase):
def setUp(self):
mock('turtle.soup',
returns=u'mock turtle')
...
これだけ。ほんと素直に mock 使おう。restore すれば元に戻ってくれる。 呼び出してみても restore されてるのが分かる。
% python -m tests
Called turtle.soup()
turtle
.
----------------------------------------------------------------------
Ran 1 test in 0.018s
OK
修正したいが名前変えたくない場合
TraceTracker などで呼び出しを追ってる場合、モックするときの名前も 重要になる。
既存テストが副作用起こしてて修正したい!けど名前変えたくない!ってときは mock_obj 引数使ってこうしよう
# turtle.soup = Mock('turtle_soup')
mock('turtle.soup'
mock_obj=Mock('turtle_soup'))
わあい
これで万事解決。
小ネタ
モック呼びだされるたびに標準出力されると、テストの結果がみにくくなる:
................F.......F..........Called turtle.soup
.......Called turtle.soup
Called turtle.soup
Called turtle.__add__
Called turtle.__add__
Called turtle.soup
...
Called turtle.soup
Called turtle.soup
.......E...s...
iMac を窓の外に放り投げる前に、 tracker=None にして落ち着こう。
Mock('turtle.__add__',
returns='Ambition',
tracker=None)
これで黙る。
まとめ
- minimock.Mock はすぐ消えるオブジェクトに適応
- モックで頑張るな
PythonでWebサーバー書きましょう
「Webサーバー書いたことある?」
と聞かれ、何じゃらホイと尋ねると
「書いたことあれば分かりそうな問題にハマってる事例見てね。みんな書いたことあるわけじゃないのね、と思って」
とのこと。
そういえば私も書いたこと無かったのでWebの悟りを開くために書いた。
書いた
- garam.py: https://gist.github.com/hirokiky/5669798
リクエストからURIとって、静的ファイルを読み込んでそのまま返す荒々しいヤツ
- 404は返せません。
- 500も返せません。
- /etc/passwdは返せます。
socket-低レベルネットワークインターフェース 読んだだけ。
周りの人の話
- とりあえずsocketで通信多重度1のstatic file返すだけのサーバー書くだけでもかなり勉強になると思うよ
- waitress 読みやすくていいよ
- GETだけなら簡単だよ
- python以外で勉強として作りたいなら C でソケット開いて、まじめにパースする
との教えが。
まとめ
自己同一性の達成過程においてWebサーバー書くことは重要らしい。
ふとWSGIサーバーとか書きたくなる。