moxの使い方
pythonのモックといえばminimockが有名ですが、私はmoxを利用しています。moxで検索してもあまり情報がないので、簡単に使い方を記載しておきます。
以下のような、URLを受け取ってソースを表示するprint_sourceという関数のテストを考えます。インターネットに接続されていない状況でもテストが通るように、urllib.urlopen()が返すsocket._fileobjectのモックを作成します。
my_urllib.py
import urllib def print_source(url): f = urllib.urlopen(url) source = f.read() print "\n", source
test_my_urllib.py
import urllib import mox import my_urllib class TestMyUrllib(object): def setUp(self): self.mox = mox.Mox() def tearDown(self): self.mox.UnsetStubs() def test_print_source(self): # モックの作成 import socket fileobject_mock = self.mox.CreateMock(socket._fileobject) self.mox.StubOutWithMock(urllib, 'urlopen') # 処理の流れの記述 urllib.urlopen('http://example.com').AndReturn(fileobject_mock) fileobject_mock.read().AndReturn("example source") # 関数の実行 self.mox.ReplayAll() my_urllib.print_source('http://example.com') self.mox.VerifyAll()
このファイルを実行すると、正しくテストが実行されていることが分かります。
$ nosetests test_my_urllib.py test_my_urllib.TestMyUrllib.test_print_source ... example source ok ---------------------------------------------------------------------- Ran 1 test in 0.001s OK
モックの作成
moxでは、モックの作成、処理の流れの記述、関数の実行というステップでテストを行います。最初に、socket._fileobjectに対応したモックを作成します。
import socket
fileobject_mock = self.mox.CreateMock(socket._fileobject)
オブジェクト名が分からなければ、CreateMockAnything()を利用することができます。
fileobject_mock = self.mox.CreateMockAnything()
また、urllib.urlopen()という関数をスタブで置き換えておきます。
self.mox.StubOutWithMock(urllib, 'urlopen')
処理の流れの記述
処理の流れは、まずurlopen()を実行し、モックfileobject_mockを返します。この際にAndReturn()を利用し、先ほど作成したモックfileobject_mockを引数として指定します。
urllib.urlopen('http://example.com').AndReturn(fileobject_mock)
引数の型だけ指定したい場合はmox.IsA(class)を使います。
urllib.urlopen(mox.IsA(str)).AndReturn(fileobject_mock)
次に、read()が呼び出された際に返すソースコードを記述しておきます。
fileobject_mock.read().AndReturn("example source")
関数の実行
mox.ReplayAll()とmox.VerifyAll()で囲まれた部分の関数を実行し、事前に記述した処理の流れと一致しているか確認します。
self.mox.ReplayAll()
my_urllib.print_source('http://example.com')
self.mox.VerifyAll()
基本的には、Mockingしたい関数があればStubOutWithMock()を使っておけば大丈夫です。より詳しく知りたい場合はSign in - Google Accountsを見てください。またmoxを使ってMySQLdbのテストを行う - tanihitoの技術メモにはmoxをMySQLdbのテストに利用する例が載っています。