unittest.mockによるpatchとpytestカスタムフィクスチャの組合せを試す
random.choiceをモックにするコードを例にする
ref: https://pycon.jp/2020/timetable/?id=203572
https://docs.python.org/ja/3/library/unittest.mock.html#unittest.mock.patch.object
環境
Python 3.9.4
pytest 6.2.5
pytest-randomly 3.11.0
以下のように書き直せた
code:test_kuji.py
import random
from unittest.mock import patch
import pytest
def kuji() -> str:
# ref: https://speakerdeck.com/mizzsugar/unittest-dot-mockwoshi-tutetesutowoshu-kou?slide=24
is_lucky = random.choice(True, False)
if is_lucky:
return "あたり"
return "はずれ"
def test_win_if_True_original():
# ref: https://speakerdeck.com/mizzsugar/unittest-dot-mockwoshi-tutetesutowoshu-kou?slide=25
with patch.object(random, "choice", return_value=True) as mocked_choice:
actual = kuji()
expected = "あたり"
assert actual == expected
@pytest.fixture()
def true_selected():
# patchを前処理としてフィクスチャに切り出した(TestCaseへのpatchのように使えるのではないかと考えている)
with patch.object(random, "choice", return_value=True) as mocked_choice:
yield
def test_win_if_True(true_selected):
# カスタムフィクスチャを使って書き直し
actual = kuji()
expected = "あたり"
assert actual == expected
# モックの呼び出しのassertionもできるか検証した
def test_lose_if_False_original():
with patch.object(random, "choice", return_value=False) as mocked_choice:
actual = kuji()
expected = "はずれ"
assert actual == expected
mocked_choice.assert_called_once_with(True, False)
@pytest.fixture()
def false_selected():
with patch.object(random, "choice", return_value=False) as mocked_choice:
yield mocked_choice
def test_lose_if_False(false_selected):
actual = kuji()
expected = "はずれ"
assert actual == expected
# false_selectedは、fixture関数でyieldしたmockオブジェクト
false_selected.assert_called_once_with(True, False)