2
1

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を使う時の備忘録

Posted at

環境構築

# Pythonのバージョンを確認
python --version
> Python 3.7.3

# pytestのインストール
> pip install pytest

# pytest-mockのインストール
> pip install pytest-mock

ファイル構成

.
├── src
│   └── script.py
└── tests
    ├── __init__.py
    └── test_script.py

テスト対象のコード

script.py
import os

# Method being tested
def delete_file(file_path):
    try:
        if not os.path.isfile(file_path):
            return 'File does not exist'
        
        os.remove(file_path)

        return 'File deleted successfully'
    except:
        return 'An error has occurred'

テストコード(retrun_valueで戻り値を固定にする)

from src.script import delete_file
import pytest

def test_file_not_exist(mocker):
    # os.path.isfile をモック化する(常にFalse)
    mocker.patch('os.path.isfile', return_value=False)

    # テスト対象を実行する
    message = delete_file('test_file_path')

    # 戻り値のメッセージを検証
    assert message == 'File does not exist'

テストコード(side_effectで任意の処理に差し替える)

from src.script import delete_file
import pytest

def test_file_not_exist(mocker):

    # os.path.isfile をモック化(isfile_mock_funcが呼ばれる)
    def isfile_mock_func(file_path):
        return False

    mocker.patch('os.path.isfile', side_effect=isfile_mock_func)

    # テスト対象の実行
    message = delete_file('test_file_path')

    # 戻り値のメッセージを検証
    assert message == 'File does not exist'

テストコード(例外を強制的に送出する)

from src.script import delete_file
import pytest

def test_file_not_exist(mocker):
    # 例外を送出するモック
    mocker.patch('os.path.isfile', side_effect=Exception)

    # テスト対象を実行する
    message = delete_file('test_file_path')

    # 戻り値のメッセージを検証
    assert message == 'File does not exist'

テストコード(モック化した処理に対する操作内容を検証する)

mocker.patch でモック化したモックオブジェクトを使うと、処理が何回呼ばれたか、どのような引数で呼ばれたかなどを検証することもできる。
例えば引数の内容と呼び出し回数をテストしたい場合以下のように書ける。

from src.script import delete_file
import pytest

def test_file_not_exist(mocker):
    # モック化
    isfile_mock = mocker.patch('os.path.isfile', return_value=True)
    remove_mock = mocker.patch('os.remove')

    # テスト対象の実行
    message = delete_file('test_file_path')

    # 戻り値のメッセージを検証
    assert message == 'File deleted successfully'

    # モック化した処理が1度だけ正しい引数で呼ばれたか検証
    isfile_mock.assert_called_once_with('test_file_path')
    remove_mock.assert_called_once_with('test_file_path')
2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?