概要
unittest は Python3 に標準で搭載されているテストモジュールです
簡単なクラスを作成してテストしてみました
環境
- macOS 10.13.5
- Python 3.6.5
テスト対象のコード
- vim mock.py
import requests
import json
class TestClient(object):
def req_get(self):
return json.loads(requests.get('https://kaka-request-dumper.herokuapp.com/').text)
def req_post(self):
return json.loads(requests.post('https://kaka-request-dumper.herokuapp.com/').text)
普通のテストコード
- vim test_mock.py
import unittest
from mock import TestClient
class TestMockClass(unittest.TestCase):
def test_get(self, mock):
cli = TestClient()
res = cli.req_get()
self.assertEqual(res['method'], 'GET')
def test_post(self):
cli = TestClient()
res = cli.req_post()
self.assertEqual(res['method'], 'POST')
if __name__ == '__main__':
unittest.main()
python3 -m unittest test_mock.py
これでテストすると実際にサーバにアクセスしてテストします
これを Mock 化してサーバにアクセスしないで各メソッドをテストします
Mock 化する
- vim test_mock.py
import unittest
import json
from mock import TestClient
from unittest.mock import patch, MagicMock
class TestMockClass(unittest.TestCase):
@patch('mock.requests')
def test_get(self, mock):
mock_res = MagicMock(text=json.dumps({'method': 'GET'}))
mock.get.return_value = mock_res
cli = TestClient()
res = cli.req_get()
self.assertEqual(res['method'], 'GET')
@patch('mock.requests')
def test_post(self, mock):
mock_res = MagicMock(text=json.dumps({'method': 'POST'}))
mock.post.return_value = mock_res
cli = TestClient()
res = cli.req_post()
self.assertEqual(res['method'], 'POST')
if __name__ == '__main__':
unittest.main()
説明
MagicMock クラスを使ってモックを作成します
ポイントは以下の 2 行です
mock_res = MagicMock(text=json.dumps({'method': 'GET'}))
mock.get.return_value = mock_res
MagicMock でモックが返却するレスポンスを作成します
今回は requests.get
が JSON を返却して、その JSON 内の method というキーをチェックします
request.get.text
で JSON 文字列が受け取れなければいけません
なので MagicMock(text=json.dumps({'method': 'GET'}))
という感じでレスポンスを作成します
text=
は request.get.text
の最後の .text
になります
.text
を参照したときに JSON 文字列が返ってきますよという宣言になります
そして作成したレスポンスを mock.get.return_value = mock_res
に設定します
mock オブジェクトはテスト用の関数 (test_get
) の引数として受け取っています
これは何かと言うとモック化した requests
になります
@patch('mock.requests')
のデコレータを付与することでそれを実現しています
mock オブジェクト (requests) の get の return_value
を先ほど作成したモックレスポンスとして設定しています
こうすることで実際にサーバにアクセスすることなくサーバと同等のレスポンスを返却する Mock を定義することができます
python3 -m unittest test_mock.py
これで実行すると実際にサーバにアクセスせずテストが成功することが確認できると思います
Tips
1 つのテスト中で複数のメソッドやクラスに対して @patch
を当てることも可能です
例えば今回のサンプルであれば
@patch('mock.requests')
@patch('mock.json')
def test_get(self, jmock, reqmock):
こんな感じで複数のモジュールに対してモックを当たられます
複数のモックを受け取るためにテストに対して複数の引数を指定しましょう
上に指定したモックが後ろの引数に入る点に注意しましょう
最後に
unittest の Mock 機能を使ってみました
基本的にはレスポンスを Mock でエミュレートして擬似的なレスポンス情報を返却させる感じだと思います
MagicMock には他にもたくさんの機能があるので詳細は参考サイトにある公式のページを参考にしてください
0 件のコメント:
コメントを投稿