Python学習【365日チャレンジ!】200日目のマスターU(@Udemy11)です。
まだ最終目標には届きませんが、200日継続できたというのは、かなり感慨深いものがあります。
これまでは頑張っても100日程度だったので、結構がんばれてるんじゃないかと思います。
目標はまだ先ですが、気持ちを引き締めて学習していこうと思います。
それでは、今日もPython学習をはじめましょう。
昨日の復習
昨日は、関数を使って疑似値をわたすことができるside_effect
を学習しました。
mock.patch
などでは、外部サービスから受け取る疑似値を直接入力して渡していましたが、渡す値を関数の返り値で受け取ることもできました。
簡単な関数であれば、直接lambda
を使って代入することもできました。
mockに関数を使った値を渡すside_effect
については、こちらの記事をごらんください。
今日は、関数を使って疑似値を返せるside_effectを使ってエラーの処理やリストを利用したテストを学習します。
test_salary.py
テストするメインのファイルはこれまでと同じsalary.pyをつかいます。
テストファイルは昨日までと同じですが、外部サービスがダウンしていてアクセスできないときなどのエラーであるConnectionRefusedError
が返されたときのコードに変更しています。
import unittest
from unittest import mock
import salary
class TestSalary(unittest.TestCase):
def setUp(self):
self.patcher = mock.patch('salary.BonusApi.bonus_price')
self.mock_bonus = self.patcher.start()
def tearDown(self):
self.patcher.stop()
def test_cal_salary_patch_side_effect(self):
self.mock_bonus.side_effect = ConnectionRefusedError
s = salary.Salary(year=2020)
salary_price = s.cal_salary()
self.assertEqual(salary_price, 150)
mock_bonus.assert_called()
ハイライトしている17行目でConnectionRefusedError
をside_effect
を使ってmock_bonus
に代入しています。
メインファイルのcal_salary
がエラーコードに対応していないため、テストを実行するとエラーを返します。
テストでメインファイルの修正が必要だとわかったので、メインファイルのcal_salary
を修正します。
cal_salary.py
メインファイルの修正は、ハイライトしている下記のコードになります。
import requests
class BonusApi(object):
def bonus_price(self, year):
req = requests.get('http://localhost/bonus', params={'year': year})
return req.json()['price']
class Salary(object):
def __init__(self, base=50, year=2020):
self.bonus_api = BonusApi()
self.base = base
self.year = year
def cal_salary(self):
# bonus = self.bonus_api.bonus_price(year=self.year)
try:
bonus = self.bonus_api.bonus_price(year=self.year)
except ConnectionRefusedError:
bonus = 0
return self.base + bonus
コメントアウトしている行をtry-except
を使ってConnectionRefusedError
が起こったときに、bonus
を0
にするコードに変更しています。
関数の計算結果は50 + 0
の50
になります。
このあと、テストファイル(test_salary.py
)の22行目の値を150
から50
に変更すれば、テストはパスします。
リストで値を入れる
side_effectは、リストで値を複数回返してテストすることができるので、外部サービスを呼び出すのが1回だけじゃなく複数回呼び出して結果が違う場合などに使うことができます。
def test_cal_salary_patch_side_effect_list(self):
self.mock_bonus.side_effect = [
100,
200,
300,
ValueError('Bankrupt')
]
s = salary.Salary(year=2020)
salary_price = s.cal_salary()
self.assertEqual(salary_price, 150)
self.mock_bonus.assert_called()
s = salary.Salary(year=2020)
salary_price = s.cal_salary()
self.assertEqual(salary_price, 250)
self.mock_bonus.assert_called()
s = salary.Salary(year=2020)
salary_price = s.cal_salary()
self.assertEqual(salary_price, 350)
self.mock_bonus.assert_called()
with self.assertRaises(ValueError):
s.cal_salary()
test_salary.py
に新しい関数を追加しました。
27行目でside_effect
にValueError
を含めた4つの値を代入しているので、合計はそれぞれ150
、250
、350
とValueError
となり、テストは問題なくパスします。
テストは大切
Pythonを学習し始めた最初のうちは、メインのファイルだけ作ればいいのですが、自分以外の大勢の人が使うようなプログラムを作るようになったら、間違いなくテストは必要です。
自分だけが使うのなら、バグがあっても直せばいいだけですが、大勢の人が使うプログラムを提供するにはバグが無いかしっかりとチェックする必要がありますので、テストは非常に重要です。
テストのコードを書くことによって、メインのファイルで不足しているところがわかることもあるので、自分以外の人に使ってもらえるプログラムがかけるようになったら、テストも並行して実行するようにしましょう!
それでは、明日もGood Python!