基本の書き方
import unittest
class TestWhateverYouWant(unittest.TestCase):
@classmethod
def setUpClass(cls):
"""
ユニットテスト開始時に一度だけ実行される
"""
pass
def setUp(self):
"""
一つ一つのテストメソッド実施前に実行される
"""
pass
def tearDown(self):
"""
一つ一つのテストメソッドの実施後に実行される
"""
pass
def test_hoge(self):
"""
テスト実行時、def test_〇〇〇 というように
testから始まるメソッドがすべて実行される
"""
pass
モックについて
テスト対象のクラスでテストが書きにくいものがあった場合にモックオブジェクトで置き換えることができる。
from unittest import mock
class TestMock(unittest.TestCase):
@mock.patch('module.ClassName2')
@mock.patch('module.ClassName1')
def test_class(self, mock1, mock2):
assert mock1 is module.ClassName1
assert mock2 is module.ClassName2
@mock.patch('module.some_method_name')
def test_method(self, mock1):
"""
some_method_name()をモックに置き換えてテストを書くことができる
"""
pass
モックは以下のように使うこともできる。
下の例では、メソッド内で使用しているrandomの実行結果をこちらから指定し、テストを書いている。
import random
class Hoge:
def return_joined_random(separator='あああ'):
hoge_list = ['AAA', 'BBB', 'CCC']
return separator.join(random.sample(hoge_list, 2))
# >> 'BBBあああCCC' とかがランダムに返ってくる
import hoge
from unittest import TestCase
from unittest import mock
class TestHoge(TestCase):
@mock.patch.object(try_mock.random, 'sample', return_value=['BBB', 'CCC'])
def test_return_joined_random(self, sample):
"""
期待する値が返ってくるかテストしたい、でもrandom使っているから固定のテストを書くのが難しい?
こういう場合はmockを使う!
"""
self.assertEqual(
hoge.Hoge().return_joined_random(separator='テスト'),
'BBBテストCCC')
def test_hoge(self):
print(hoge.random.sample([1,2,3], 2))
ポイントはテストメソッド宣言の真上に書いてあるこの部分⬇️
@mock.patch.object(hoge.random, 'sample', return_value=['BBB', 'CCC'])
これは、「hogeモジュール(hoge.py)でimportしているrandomのsample関数はreturn_valueを['BBB', 'CCC'] とする」 という意味。
ランダム要素であるrandomの実行結果をこっちが予め定義することで、その結果だった場合のテストをすることができる。すなわちrandomの動作を気にすることなく単体テストを書くことができるのだ。
ちなみにtest_hoge()
の結果は[2, 3] など普通にrandom.sample()の実行結果が返ってくる。
このことにより、パッチは当てたメソッドにのみ作用することがわかる。
(random.sample() 全体に効いちゃってたら、ここでもreturn_value が['BBB', 'CCC'] になっているはずだから)
参考
https://docs.python.org/ja/3/library/unittest.html
https://docs.python.org/ja/3/library/unittest.mock.html
https://blog.amedama.jp/entry/python-unittest