pythonテストコードの書き方(Moc)
| 登録日 | :2025/07/22 19:10 |
|---|---|
| カテゴリ | :Python基礎 |
Mocをすることでテストを書くサンプル
以下のsalary.pyを、Mocを使ってテストをするサンプルコード
salary.py
import requests
class ThirdPartyBonusRestApi(object):
def __init__(self):
self.url = 'http://localhost/bonus'
@staticmethod
def get_api_name():
return 'Bonus!'
def bonus_price(self, year):
r = requests.get(self.url, params={'year': year})
return r.json()['price']
class Salary(object):
def __init__(self, base=100, year=2017):
self.bonus_api = ThirdPartyBonusRestApi()
self.base = base
self.year = year
def calculation_salary(self):
bonus = 0
if self.year < 2020:
try:
bonus = self.bonus_api.bonus_price(year=self.year)
except ConnectionRefusedError:
bonus = 0
return self.base + bonus
test_salary.py(テストコード)
import unittest
from unittest.mock import MagicMock
from unittest import mock
from test.mock import salary
class TestSalary(unittest.TestCase):
def test_calculation_salary(self):
s = salary.Salary(year=2017)
s.bonus_api.bonus_price = MagicMock(return_value=1)
self.assertEqual(s.calculation_salary(), 101)
s.bonus_api.bonus_price.assert_called()
s.bonus_api.bonus_price.assert_called_once()
s.bonus_api.bonus_price.assert_called_with(year=2017)
self.assertEqual(s.bonus_api.bonus_price.call_count, 1)
def test_calculation_salary_no_bonus(self):
s = salary.Salary(year=2050)
s.bonus_api.bonus_price = MagicMock(return_value=0)
self.assertEqual(s.calculation_salary(), 100)
s.bonus_api.bonus_price.assert_not_called()
def test_calculation_salary_patch_with(self):
with mock.patch('test.mock.salary.ThirdPartyBonusRestApi.bonus_price') as mock_bonus:
mock_bonus.return_value = 1
s = salary.Salary(year=2017)
salary_price = s.calculation_salary()
self.assertEqual(salary_price, 101)
mock_bonus.assert_called()
def setUp(self):
self.patcher = mock.patch('test.mock.salary.ThirdPartyBonusRestApi.bonus_price')
self.mock_bonus = self.patcher.start()
def tearDown(self) -> None:
self.patcher.stop()
def test_calculation_salary_patcher(self):
self.mock_bonus.return_value = 1
s = salary.Salary(year=2017)
salary_price = s.calculation_salary()
self.assertEqual(salary_price, 101)
self.mock_bonus.assert_called()
def test_calculation_salary_side_effect(self):
def f(year):
if year < 2020:
return 1
return 0
# self.mock_bonus.side_effect = f
# self.mock_bonus.side_effect = ConnectionRefusedError
self.mock_bonus.side_effect = [1, 2, 3, ValueError('Bankrupt!!!')]
s = salary.Salary(year=2017)
salary_price = s.calculation_salary()
self.assertEqual(salary_price, 101)
s = salary.Salary(year=2017)
salary_price = s.calculation_salary()
self.assertEqual(salary_price, 102)
s = salary.Salary(year=2017)
salary_price = s.calculation_salary()
self.assertEqual(salary_price, 103)
s = salary.Salary(year=200)
with self.assertRaises(ValueError):
s.calculation_salary()
self.mock_bonus.assert_called()
@mock.patch('test.mock.salary.ThirdPartyBonusRestApi', spec=True)
def test_calculation_salary_class(self, mock_rest):
mock_rest = mock_rest.return_value
mock_rest.bonus_price.return_value = 1
mock_rest.get_api_name.return_value = 'Money'
s = salary.Salary(year=2017)
salary_price = s.calculation_salary()
self.assertEqual(salary_price, 101)
mock_rest.bonus_price.assert_called()