Closed5
Python3_unittestモジュール, unittest.mockモジュール
Python実践レシピより
Python3エンジニア認定実践試験メモ
テスト対象のコード
target.py
# coding: utf-8
# 正しい結果を返す関数
def div_ok(a, b):
return a / b
# 間違えた結果を返す関数
def div_ng(a, b):
return 1.0
テスト実行コード
main.py
import unittest
from target import div_ok, div_ng
# TestCaseクラスを継承
class DivTest(unittest.TestCase):
# test_xxxの名前で関数を用意
def test_the_div_of_two_integers(self):
actual = div_ok(6, 3)# テスト対象を実行(正しい結果を返す関数)
#actual = div_ng(6, 3)# テスト対象を実行(間違えた結果を返す関数)
expected = 2.0
self.assertEqual(actual, expected)# 値が等しいか確認
if __name__ == "__main__":
unittest.main()# テストを実行する
テストの実行と結果
command
python3 main.py
output
div_ok関数の場合(正しい結果を返す関数をテストした場合)
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
div_ng関数の場合(間違った結果を返す関数をテストした場合)
F
======================================================================
FAIL: test_the_div_of_two_integers (__main__.DivTest.test_the_div_of_two_integers)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/xxx(省略)", line 20, in test_the_div_of_two_integers
self.assertEqual(actual, expected)
AssertionError: 1.0 != 2.0
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (failures=1)
テスト対象のコード
target.py
# 正しい結果を返す関数
def div_ok(a, b):
return a / b
# 間違えた結果を返す関数
def div_ng(a, b):
return 1.0
テスト実行コード
main.py
import unittest
from target import div_ok
# 割り算の結果を格納している配列
# 1件目は正しい結果、2件目と3件目は間違った結果を格納
examples = [
[6, 3, 2.0],
[6, 2, 5.0],
[6, 1, 4.0]
]
# TestCaseクラスを継承
class DivTest(unittest.TestCase):
# test_xxxの名前で関数を用意
def test_the_div_of_two_integers(self):
# データを順番に取り出す
for idx, example in enumerate(examples):
# 1件づつテストデータを取り出す
a, b, expected = example
# subTestの引数にテストデータを渡す
with self.subTest(f"{a}/{b}={expected}", idx=idx):
self.assertEqual(div_ok(a, b), expected)# テスト実行(正しい結果を返す関数)
if __name__ == "__main__":
unittest.main()# テストを実行する
テストの実行と結果
command
python3 main.py
output
FF
======================================================================
FAIL: test_the_div_of_two_integers (__main__.DivTest.test_the_div_of_two_integers) [6/2=5.0] (idx=1)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/xxx(省略)", line 30, in test_the_div_of_two_integers
self.assertEqual(div_ok(a, b), expected)# テスト実行
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 3.0 != 5.0
======================================================================
FAIL: test_the_div_of_two_integers (__main__.DivTest.test_the_div_of_two_integers) [6/1=4.0] (idx=2)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/xxx(省略)", line 30, in test_the_div_of_two_integers
self.assertEqual(div_ok(a, b), expected)# テスト実行
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 6.0 != 4.0
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (failures=2)
テストの事前処理に使う
SetUp
main.py
import unittest
class SetUpAndSetUpClassTest(unittest.TestCase):
def setUp(self):
print("setUp!!")
@classmethod
def setUpClass(clz):
print("setUpClass!!")
def test_hop(self):
print("test_hop!!")
def test_step(self):
print("test_step!!")
def test_jump(self):
print("test_jump!!")
if __name__ == "__main__":
unittest.main()# テストを実行する
実行と結果
command
python3 main.py
実行の順番に注目
main.py
setUpClass!!
setUp!!
test_hop!!
.setUp!!
test_jump!!
.setUp!!
test_step!!
.
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK
テストの事後処理に使う
TearDown
main.py
import unittest
class TearDownAndTearDownClassTest(unittest.TestCase):
def tearDown(self):
print("tearDown!!")
@classmethod
def tearDownClass(clz):
print("tearDownClass!!")
def test_hop(self):
print("test_hop!!")
def test_step(self):
print("test_step!!")
def test_jump(self):
print("test_jump!!")
if __name__ == "__main__":
unittest.main()# テストを実行する
実行と結果
command
python3 main.py
実行の順番に注目
output
test_hop!!
tearDown!!
.test_jump!!
tearDown!!
.test_step!!
tearDown!!
.tearDownClass!!
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK
MagicMock
テスト対象のクラス
api_shopping.py
class ShoppingAPI:
def get_items(self, name):# 中身を確認(テスト対象)
return ["商品1", "商品2", "商品3"]
def add_item(self, name):# 追加(使っていない)
pass
def remove_item(self, name):# 削除(使っていない)
pass
def purchase_items(self):# 清算(使っていない)
pass
実行と結果
main.py
from unittest.mock import MagicMock
from api_shopping import ShoppingAPI
# テスト対象のクラス
api = ShoppingAPI()
# テスト対象の関数をMagicMockで上書き
api.get_items = MagicMock()
print(api.get_items)# 上書きを確認
# <MagicMock id='4493138336'>
# テスト対象の関数の戻り値を設定する
api.get_items.return_value = ["モック1", "モック2", "モック3"]
print(api.get_items("商品1"))
# ['モック1', 'モック2', 'モック3']
# テスト対象の関数に例外を設定できる
api.get_items.side_effect = Exception("例外を設定します")
print(api.get_items("商品1"))
# Traceback (most recent call last):
# ...(省略)
# Exception: 例外を設定します
このスクラップは2ヶ月前にクローズされました