1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

pytest の mock を使ってみる【Python】

Posted at

やりたいこと

Pythonのテストフレームワークのひとつ「pytest」の「モック」と呼ばれる機能に入門する。

環境

  • macOS Monterey 12.2.1
  • python 3.8.10
  • pytest 7.0.1
  • pytest-mock 3.7.0

モックとは

  • 「モックアップ」の略。モックアップとは、要はハリボテのこと。実際の機能は持っていないけど、外から見たらその機能を持っているかのように見せることができます。
  • pytestにおけるモックには「pytest-mock」ライブラリを使用します。

インストール

pipで各種ライブラリをインストールします。

$ pip install pytest pytest-mock

モックを使う方法

以下のようなディレクトリ構成のファイルを題材として使います。

.
├── src
│   └── mock_target.py
└── tests
    ├── __init__.py
    └── test_mock_target.py

モック化を行うときは mocker.patch("モック化したいオブジェクト", モック化の種類)のように指定します。
「パッチ」って、なにかにペタっと貼って隠すやつだと思うので、なんとなくニュアンスが理解できます。(?)

関数が返す値を固定する

題材として使うテスト対象コードは以下です。
sample_function()は、半々の確率でTrueかFalseを返します。

mock_target.py
import random

def sample_function():
    random_number = random.randint(1, 20)
    return random_number % 2 == 0

モックを使用したテストコードは以下のようになります。
動的に値を指定したい場合は return_value を使います。

test_mock_target.py
import os
import sys

sys.path.append(os.path.join(os.path.dirname(__file__), '..'))

from src.mock_target import sample_function

def test_sample_function(mocker):   # 引数にmockerをいれる
    # mocker.patch('モック化したいオブジェクト', return_value=固定したい値)
    mocker.patch("src.mock_target.sample_function", return_value=True)
    assert sample_function() is True

モックを使わず assert sample_function() is True とテストした場合、本来は半々の確率で成功か失敗となりますが、
モックを使い、 sample_function() の返り値を「True」で固定することにより、つねにこのテストが成功することになります。

関数が返す値を動的に指定する

題材として使うテスト対象コードは以下です。
int型のnumを引数にとるsample_function()は、ランダムにTrueかFalseを返します。

mock_target.py
import random

def sample_function(num: int):
    random_number = num + random.randint(1, 20)
    return random_number % 2 == 0

モックを使用したテストコードは以下のようになります。
動的に値を指定したい場合は side_effect を使います。

test_mock_target.py
import os
import sys

sys.path.append(os.path.join(os.path.dirname(__file__), '..'))

from src.mock_target import sample_function

def return_pattern(num: int):
    if num % 2 == 0:
        return True
    else:
        return False

def test_sample_function(mocker):   # 引数にmockerをいれる
    # mocker.patch('モック化したいオブジェクト', side_effect=動的な値を指定した関数)
    mocker.patch("src.mock_target.sample_function", side_effect=return_pattern)
    assert sample_function(6) is True

モックを使わず assert sample_function(6) is True とテストした場合、本来はランダムに成功か失敗となりますが、
モックを使い、
「numに偶数を指定した時はsample_function(num)の返り値も偶数となる」「numに奇数を指定した時はsample_function(num)の返り値も奇数となる」と動的に関数の返り値を指定することで、
sample_function(6) の返り値を「True」で固定することができ、つねにこのテストが成功することになります。

参考にした記事

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?