はじめに
PE部の谷です。
先日、unittestの超基本を学び、実践で書いてみたいと思っていたら機会がありました。
unittestとは
Pythonコードのテストを行う上で有用な機能が実装されたモジュールのこと。
unittest、テストコードって何だろう?という方は、以前書いた初心者向けのブログがあるのでそちらをご覧ください。 blog.serverworks.co.jp
詳細については、公式ドキュメントを参照してください。
テスト対象コード
今回、テストを行うのは、こちらのブログで紹介したZendeskの組織情報を更新するコードの一括更新の部分です。
executable.py
def bulk_update(updated_info_list): """ 一括更新 """ try: job_status_list = [] size = 100 for start in range(0, len(updated_info_list), size): job_status = zenpy_client.organizations.update( updated_info_list[start: start + size] ) job_status_list.append(job_status) return job_status_list except Exception as e: logger.exception('例外が発生しました: %s', e)
テストコード
import unittest import executable from unittest.mock import MagicMock, patch class TestZendeskMethods(unittest.TestCase): @patch('executable.zenpy_client') def test_bulk_update(self, mock_zenpy_client): mock_job_status = { "job_status": { "id": "111111111111111111111111111111111111111", "url": "https://zendesk.com/api/v2/job_statuses/111111111111111111111111111111111111111.json", "total": 3, "progress": 3, "status": "completed", "message": "Completed at 2021-10-27 03:05:55 +0000", "results": [ {"action":"update","status":"Updated","success":True,"id":222222222222}, {"action":"update","status":"Updated","success":True,"id":333333333333}, {"action":"update","status":"Updated","success":True,"id":444444444444} ] } } mock_zenpy_client.organizations.update.return_value = mock_job_status less_100_result = executable.bulk_update(list(range(0,77))) more_100_result = executable.bulk_update(list(range(0,1540))) self.assertEqual(len(less_100_result), 1) self.assertEqual(len(more_100_result), 16) self.assertNotEqual(less_100_result, more_100_result) with self.assertRaises(Exception): executable.bulk_update()
test_bulk_update関数
渡されたリストの要素数によって意図した動きをしてくれるかをテストします。
要素の数が100件以上の時、100件未満の時、結果の要素数が幾つになるかを比較します。
ここで厄介なのは、外部APIを呼び出しているzenpy_client.organizations.update
です。
結果が接続先に依存しているため、この依存を切り離さなければいけません。
任意の戻り値を返すようにします。
unittest.mock.patch
をデコレーターで利用して、'executable.zenpy_client'
を引数に指定することでexecutable.pyで使っているzenpy_client
をモックに置き換えます。
置き換えたモックはtest_bulk_update
の引数mock_zenpy_client
で受け取り、関数内で使えるようにします。
mock_zenpy_client.organizations.update.return_value = mock_job_status
でzenpy_client.organizations.update
の戻り値をダミーのレスポンスに置き換えています。
ダミーレスポンスはmock_job_status
で定義しています。
まとめ
モックを使って外部APIとの依存を切り離すことができました。