この記事で解説すること3つ
皆さんは、pytestを用いてテストコードを書くことはありますか?
最近、私は以下のような実装結果に対して、テストコードを書く必要がありました。
# usecase1.py
try:
# 想定:numpyがインストールされておらず、読み込めない
import numpy
g_can_load = True
except:
# 例外が発生したら、代替モジュールを読み込む
import math
g_can_load = False
また、以下に示すように、逆の状況にも遭遇しています。
# usecase2.py
try:
# 想定:インストール済みで問題なく読み込めるモジュール
import math
g_can_load = True
except:
# 例外が発生したら、自作モジュールを読み込む
import original_math
g_can_load = False
今回は、上記のようなPython scriptに対し、pytestでテストを行う方法を解説します。
Pythonの仕様上、癖がある部分もあったので、備忘録として残しておきます。

GitHub上に実際に動かすことができるコード一式も用意したので、手元で動かしながら確認してみてください。
全体構成
ディレクトリ構成、動作確認環境、テスト対象ファイルの詳細について解説します。
ディレクトリ構成
今回想定するディレクトリ構成は、以下に示す通りです。
./
|-- docker-compose.yml
|-- LICENSE
|-- README.md
|-- env.sample
|-- .env
|-- docker/
| |-- bashrc
| |-- Dockerfile
| |-- pyproject.toml
| `-- waiting.sh
`-- app/
|-- src/
| |-- __init__.py
| |-- main.py
| |-- newton.py
| |-- private.py ← テスト対象が参照するファイル
| |-- target_module.py ← テスト対象が参照するファイル
| `-- sample_with_having_errors.py ← 今回のテスト対象
`-- tests/
|-- __init__.py
|-- conftest.py
|-- test_main.py
|-- test_newton.py
`-- test_target_module.py ← 今回のメインコード
GitHub上の構成をそのまま反映しているため、適宜コメントもあわせてご覧ください。

動作確認環境
今回は、以下の環境で動作確認を行いました。
項目 | 詳細 | 確認方法 |
---|---|---|
デバイス | Raspberry Pi 4 Model B Rev 1.4 | cat /proc/cpuinfo | sed -e "s/\s\s*/ /g" | grep -oP "(?<=Model : )(.*)" |
アーキテクチャ | aarch64 (64bit) | uname -m |
OS | Debian GNU/Linux 11 (bullseye) | cat /etc/os-release | grep -oP '(?<=PRETTY_NAME=")(.*)(?=")' |
さらに、Dockerを用いて検証を行っているため、Docker環境さえあれば、ほとんどの方が実行結果を再現できるようになっています。
Poetryというpythonの仮想環境も利用しているので、pythonが動く環境があればそれでもOKです。

テスト対象ファイル
今回のテスト対象のコードは、以下に示す通りです。
# sample_with_having_errors.py
# 下記の2つのモジュールは存在しない
import disabled_module
from cannot_use_package.cannot_use_module import disabled_function
def execute(x):
y1 = disabled_module.undefined_function(x + 1)
y2 = disabled_function(x + 2)
y = y1 + y2
return y
# private.py
# Assumption
# - This file is private.
# - This file is ignored for git's configuration management.
# target_module.py
# ==============
# Test pattern 1
# ==============
try:
import src.sample_with_having_errors
g_sample = True
except:
g_sample = False
# ==============
# Test pattern 2
# ==============
try:
import src.private
g_private = True
except:
g_private = False
実際に確認したいことなどは、次の章で解説したいと思います。
今回やりたいこと
コードベースになりますが、今回やりたいことを説明します。
順に解説します。
テスト時にImportErrorの例外を発生させない
テスト対象コードのうち、前半部分を再掲します。
# target_module.py
# ==============
# Test pattern 1
# ==============
try:
import src.sample_with_having_errors
g_sample = True
except:
g_sample = False
上記のimport文ですが、src.sample_with_having_errors
は、以下のようになっているため、例外が発生します。
# sample_with_having_errors.py
# 下記の2つのモジュールは存在しない
import disabled_module
from cannot_use_package.cannot_use_module import disabled_function
# 以下、省略
このため、グローバル変数g_sample
は必ずFalse
になります。
今回は、テストコードを工夫して、src.sample_with_having_errors
をimportする際に例外が発生しないようにテストを行うことが目的になります。
テスト時に意図的にImportErrorの例外を発生させる
続いて、テスト対象コードのうち、後半部分を紹介します。
# target_module.py
# 中略
# ==============
# Test pattern 2
# ==============
try:
import src.private
g_private = True
except:
g_private = False
上記は先ほどと逆の動きをし、src.private
をimportする際に例外は発生しないため、g_private
は必ずTrue
になります。
今回は、テストコードを工夫して、src.private
をimportする際に例外が発生するようにテストを行うことが目的になります。
以上のことをまとめると、以下のように整理できますね。
テスト観点 | やりたいこと | 注目する変数 | 通常実行時の値 | テスト時の出力 |
---|---|---|---|---|
import時に例外が発生する | import時に発生する例外を抑制したい | g_sample | False | True |
import時に例外が発生しない | import時に意図的に例外を発生させたい | g_private | True | False |
ImportError関連の例外処理テストを行う際の考え方
今回のテストを行う際は、import時にpythonの内部で何が行われるかを知る必要があります。
pythonのimport処理はimportlib
にて実現されているため、該当するコードの一部を記載します。
import importlib.util
import sys
def import_module(name, package=None):
"""An approximate implementation of import."""
absolute_name = importlib.util.resolve_name(name, package)
try:
return sys.modules[absolute_name]
except KeyError:
pass
path = None
if '.' in absolute_name:
parent_name, _, child_name = absolute_name.rpartition('.')
parent_module = import_module(parent_name)
path = parent_module.__spec__.submodule_search_locations
for finder in sys.meta_path:
spec = finder.find_spec(absolute_name, path)
if spec is not None:
break
else:
msg = f'No module named {absolute_name!r}'
raise ModuleNotFoundError(msg, name=absolute_name)
module = importlib.util.module_from_spec(spec)
sys.modules[absolute_name] = module
spec.loader.exec_module(module)
if path is not None:
setattr(parent_module, child_name, module)
return module
こちらのページにあるコードを参照しました。

上記から読み取れる3つのことは、以下に示す通りです。
参照したコードから分かること3つ
- 一度importしたモジュールは、
sys,modules
にキャッシュされる。 - モジュールロード時は、探索時のモジュール名を変更しながら再帰的に処理される。(15行目)
- モジュールが見つからない場合は、
ModuleNotFoundError
の例外が投げられる。
以上のことを踏まえると、以下のようにテストコードを作成すれば、テストが実施できると考えられます。
テストコードの作成方針
- ImportErrorが発生する場合
sys.modules
にある該当モジュールをモックに差し替える。 - 正常に読み込める場合
sys.modules
にある該当モジュールを削除した上で、モジュール探索時に例外を投げる。
文字だけではイメージしづらいと思うので、テストコードの実装結果もあわせて説明します。
テストコードの実装例
今回、実装したテストコードは以下のようになります。
import pytest
@pytest.fixture
def get_resetter_of_sys_modules(mocker):
def module_setter(remove_cached_modules=None, mocker_modules=None):
# 初期化
remove_cached_modules = remove_cached_modules or []
mocker_modules = mocker_modules or []
# キャッシュ済みのモジュールの削除
import sys
_fake_modules = {key: val for key, val in sys.modules.items() if key not in remove_cached_modules}
# 指定したモジュールをモック化
for key in mocker_modules:
_fake_modules[key] = mocker.Mock()
# sys.moduleにpatchを当てる
mocker.patch.dict('sys.modules', _fake_modules, clear=True)
return module_setter
@pytest.mark.abnormal
def test_cannot_load_specific_files(get_resetter_of_sys_modules):
module_setter = get_resetter_of_sys_modules
# キャッシュ済みのモジュールを削除
module_setter(remove_cached_modules=[
'src.target_module',
'src.sample_with_having_errors',
'disabled_module',
'cannot_use_package.cannot_use_module',
])
# ==================
# Import test module
# ==================
# [注意] `from src import target_module as tm` とすると、pythonでは独立してロードされるため、今回のケースでは適さない
import src.target_module as tm
assert not tm.g_sample
@pytest.mark.normal
def test_avoid_raising_import_exception(get_resetter_of_sys_modules):
module_setter = get_resetter_of_sys_modules
# キャッシュ済みのモジュールを削除し、対象のモジュールをモック化
module_setter(
remove_cached_modules=['src.target_module', 'src.sample_with_having_errors'],
mocker_modules=['disabled_module', 'cannot_use_package.cannot_use_module'],
)
# ==================
# Import test module
# ==================
# [注意] `from src import target_module as tm` とすると、pythonでは独立してロードされるため、今回のケースでは適さない
import src.target_module as tm
assert tm.g_sample
@pytest.mark.normal
def test_can_load_private_file(get_resetter_of_sys_modules):
module_setter = get_resetter_of_sys_modules
# キャッシュ済みのモジュールを削除
module_setter(remove_cached_modules=[
'src.target_module',
'src.private',
])
# ==================
# Import test module
# ==================
import src.target_module as tm
assert tm.g_private
@pytest.mark.abnormal
def test_raise_import_exception_with_existing_file(get_resetter_of_sys_modules, mocker):
module_setter = get_resetter_of_sys_modules
# キャッシュ済みのモジュールを削除
module_setter(remove_cached_modules=[
'src.target_module',
'src.private',
])
# モジュール探索用の関数を定義
import importlib
original_finder = importlib._bootstrap._find_and_load
def _fake_finder(name, *args, **kwargs):
# 特定のモジュールに対して、例外を投げる
if name == 'src.private':
raise Exception()
return original_finder(name, *args, **kwargs)
# モジュール探索用の関数を参照するよう、オリジナルの実装にpatchを当てる
mocker.patch('importlib._bootstrap._find_and_load', side_effect=_fake_finder)
# ==================
# Import test module
# ==================
import src.target_module as tm
assert not tm.g_private
@pytest.mark.normal
def test_execute_func(get_resetter_of_sys_modules, mocker):
module_setter = get_resetter_of_sys_modules
# キャッシュ済みのモジュールを削除し、対象のモジュールをモック化
module_setter(
remove_cached_modules=['src.target_module', 'src.sample_with_having_errors'],
mocker_modules=['disabled_module', 'cannot_use_package.cannot_use_module'],
)
# 期待値を設定
ret_y1 = 4
ret_y2 = 5
y_sum = ret_y1 + ret_y2
# 該当モジュールをモック化
import sys
disabled_module_mocker = sys.modules['disabled_module']
mocker.patch.object(disabled_module_mocker, 'undefined_function', return_value=ret_y1)
mocker.patch('src.sample_with_having_errors.disabled_function', return_value=ret_y2)
import src.sample_with_having_errors as swhe
estimate_y = swhe.execute(1)
assert estimate_y == y_sum
Github上のファイルは、こちらになります。
以降では、コアになる部分(fixture部分)とテストコードの書き方の例について、紹介します。
コア部分と書き方の例
モジュールをモックする処理は、こちらの記事も参考にしました。

コア部分
コア部分では、以下の3つを実現しています。
コア部分で実現していること3つ
sys.modules
から指定したモジュールを削除する。- 指定したモジュールのモックを作成し、
sys.modules
に設定する。 - 書き換えた
sys.modules
が呼び出されるように、patchを当てる。
実装結果の該当箇所は、以下に示す通りです。
@pytest.fixture
def get_resetter_of_sys_modules(mocker):
def module_setter(remove_cached_modules=None, mocker_modules=None):
# 初期化
remove_cached_modules = remove_cached_modules or []
mocker_modules = mocker_modules or []
# キャッシュ済みのモジュールの削除
import sys
_fake_modules = {key: val for key, val in sys.modules.items() if key not in remove_cached_modules}
# 指定したモジュールをモック化
for key in mocker_modules:
_fake_modules[key] = mocker.Mock()
# sys.moduleにpatchを当てる
mocker.patch.dict('sys.modules', _fake_modules, clear=True)
return module_setter
上記のうち、以下の処理により「sys.modules
から指定したモジュールを削除する」という処理を実現しています。
_fake_modules = {key: val for key, val in sys.modules.items() if key not in remove_cached_modules}

また、以下の処理にて、「指定したモジュールのモックを作成し、sys.modules
に設定する」という処理を実現しています。
for key in mocker_modules:
_fake_modules[key] = mocker.Mock()

最後に、下記を実行することで、「書き換えたsys.modules
が呼び出される」ことになりますよ。
mocker.patch.dict('sys.modules', _fake_modules, clear=True)
以上がコア部分の実装になります。
以降では、実際に関連機能をテストしながら、動作確認を行っていきましょう。
ImportErrorを発生させない場合のテストコードの例
まず、従来通り、ImportErrorが発生するケースを示します。
@pytest.mark.abnormal
def test_cannot_load_specific_files(get_resetter_of_sys_modules):
module_setter = get_resetter_of_sys_modules
# キャッシュ済みのモジュールを削除
module_setter(remove_cached_modules=[
'src.target_module',
'src.sample_with_having_errors',
'disabled_module',
'cannot_use_package.cannot_use_module',
])
# ==================
# Import test module
# ==================
# [注意] `from src import target_module as tm` とすると、pythonでは独立してロードされるため、今回のケースでは適さない
import src.target_module as tm
assert not tm.g_sample
こちらは、普通に呼び出しているだけなので、g_sample
の値は必ずFalseになります。
pytest tests/test_target_module.py::test_cannot_load_specific_files
(out)==================================================================================== test session starts ====================================================================================
(out)platform linux -- Python 3.12.10, pytest-8.3.5, pluggy-1.6.0 -- /usr/local/bin/python3.12
(out)cachedir: home/.cache
(out)Using --randomly-seed=1702629328
(out)rootdir: /opt
(out)configfile: pyproject.toml
(out)plugins: env-1.1.5, randomly-3.16.0, mock-3.14.1, cov-6.1.1, anyio-4.9.0, asyncio-0.26.0
(out)asyncio: mode=Mode.STRICT, asyncio_default_fixture_loop_scope=session, asyncio_default_test_loop_scope=session
(out)collected 1 item
(out)
(out)tests/test_target_module.py::test_cannot_load_specific_files PASSED [100%]
(out)
(out)====================================================================================== tests coverage =======================================================================================
(out)_____________________________________________________________________ coverage: platform linux, python 3.12.10-final-0 ______________________________________________________________________
(out)
(out)Coverage HTML written to dir htmlcov
(out)Coverage XML written to file coverage.xml
(out)===================================================================================== 1 passed in 0.49s ====================================================================================
続いて、読み込めないモジュールをモック化した場合のケースです。
@pytest.mark.normal
def test_avoid_raising_import_exception(get_resetter_of_sys_modules):
module_setter = get_resetter_of_sys_modules
# キャッシュ済みのモジュールを削除し、対象のモジュールをモック化
module_setter(
remove_cached_modules=['src.target_module', 'src.sample_with_having_errors'],
mocker_modules=['disabled_module', 'cannot_use_package.cannot_use_module'],
)
# ==================
# Import test module
# ==================
# [注意] `from src import target_module as tm` とすると、pythonでは独立してロードされるため、今回のケースでは適さない
import src.target_module as tm
assert tm.g_sample
この場合、読み込めないモジュールをモック化しているので、正常に読み込むことができたことになり、テストもパスします。
pytest tests/test_target_module.py::test_avoid_raising_import_exception
(out)==================================================================================== test session starts ====================================================================================
(out)platform linux -- Python 3.12.10, pytest-8.3.5, pluggy-1.6.0 -- /usr/local/bin/python3.12
(out)cachedir: home/.cache
(out)Using --randomly-seed=2230336766
(out)rootdir: /opt
(out)configfile: pyproject.toml
(out)plugins: env-1.1.5, randomly-3.16.0, mock-3.14.1, cov-6.1.1, anyio-4.9.0, asyncio-0.26.0
(out)asyncio: mode=Mode.STRICT, asyncio_default_fixture_loop_scope=session, asyncio_default_test_loop_scope=session
(out)collected 1 item
(out)
(out)tests/test_target_module.py::test_avoid_raising_import_exception PASSED [100%]
(out)
(out)====================================================================================== tests coverage =======================================================================================
(out)_____________________________________________________________________ coverage: platform linux, python 3.12.10-final-0 ______________________________________________________________________
(out)
(out)Coverage HTML written to dir htmlcov
(out)Coverage XML written to file coverage.xml
(out)===================================================================================== 1 passed in 0.53s =====================================================================================
意図的にImportErrorを発生させる場合のテストコードの例
まず、従来通り、ImportErrorが発生しないケースを示します。
@pytest.mark.normal
def test_can_load_private_file(get_resetter_of_sys_modules):
module_setter = get_resetter_of_sys_modules
# キャッシュ済みのモジュールを削除
module_setter(remove_cached_modules=[
'src.target_module',
'src.private',
])
# ==================
# Import test module
# ==================
import src.target_module as tm
assert tm.g_private
こちらは、src/private.py
が存在するため、g_private
は必ずTrue
になります。
pytest tests/test_target_module.py::test_raise_import_exception_with_existing_file
==================================================================================== test session starts ====================================================================================
platform linux -- Python 3.12.10, pytest-8.3.5, pluggy-1.6.0 -- /usr/local/bin/python3.12
cachedir: home/.cache
Using --randomly-seed=4106986825
rootdir: /opt
configfile: pyproject.toml
plugins: env-1.1.5, randomly-3.16.0, mock-3.14.1, cov-6.1.1, anyio-4.9.0, asyncio-0.26.0
asyncio: mode=Mode.STRICT, asyncio_default_fixture_loop_scope=session, asyncio_default_test_loop_scope=session
collected 1 item
tests/test_target_module.py::test_raise_import_exception_with_existing_file PASSED [100%]
====================================================================================== tests coverage =======================================================================================
_____________________________________________________________________ coverage: platform linux, python 3.12.10-final-0 ______________________________________________________________________
Coverage HTML written to dir htmlcov
Coverage XML written to file coverage.xml
===================================================================================== 1 passed in 0.51s ====================================================================================
続いて、意図的に例外を呼び出す場合の実装例です。
@pytest.mark.abnormal
def test_raise_import_exception_with_existing_file(get_resetter_of_sys_modules, mocker):
module_setter = get_resetter_of_sys_modules
# キャッシュ済みのモジュールを削除
module_setter(remove_cached_modules=[
'src.target_module',
'src.private',
])
# モジュール探索用の関数を定義
import importlib
original_finder = importlib._bootstrap._find_and_load
def _fake_finder(name, *args, **kwargs):
# 特定のモジュールに対して、例外を投げる
if name == 'src.private':
raise Exception()
return original_finder(name, *args, **kwargs)
# モジュール探索用の関数を参照するよう、オリジナルの実装にpatchを当てる
mocker.patch('importlib._bootstrap._find_and_load', side_effect=_fake_finder)
# ==================
# Import test module
# ==================
import src.target_module as tm
assert not tm.g_private
この時のポイントとして、モジュール探索用の関数を自前で定義していることが挙げられます。
今回の場合、読み込むモジュールに応じて、以下のように場合分けできます。
読み込めないモジュールによる場合分け2パターン
src.private
を読み込む
例外を投げるsrc.private
以外を読み込む
そのまま読み込む
上記を実現したいことを踏まえると、モジュール探索用の関数は、以下のようにすれば良いことが分かりますね。
import importlib
original_finder = importlib._bootstrap._find_and_load
def _fake_finder(name, *args, **kwargs):
# 特定のモジュールに対して、例外を投げる
if name == 'src.private':
raise Exception()
return original_finder(name, *args, **kwargs)
このような処理を組み込んだ上でテストを行うと、g_private
がFalse
になり、テストをパスしていることが分かります。
pytest tests/test_target_module.py::test_raise_import_exception_with_existing_file
==================================================================================== test session starts ====================================================================================
platform linux -- Python 3.12.10, pytest-8.3.5, pluggy-1.6.0 -- /usr/local/bin/python3.12
cachedir: home/.cache
Using --randomly-seed=2832467546
rootdir: /opt
configfile: pyproject.toml
plugins: env-1.1.5, randomly-3.16.0, mock-3.14.1, cov-6.1.1, anyio-4.9.0, asyncio-0.26.0
asyncio: mode=Mode.STRICT, asyncio_default_fixture_loop_scope=session, asyncio_default_test_loop_scope=session
collected 1 item
tests/test_target_module.py::test_raise_import_exception_with_existing_file PASSED [100%]
====================================================================================== tests coverage =======================================================================================
_____________________________________________________________________ coverage: platform linux, python 3.12.10-final-0 ______________________________________________________________________
Coverage HTML written to dir htmlcov
Coverage XML written to file coverage.xml
===================================================================================== 1 passed in 0.55s ====================================================================================
【おまけ】モック化した後のモジュールの利用例
モック化するのは良いですが、実際にはモック化した上でテストを行うケースが多いと思います。
モック化するのは、スタブを用意していることと同義ですね。

このため、モック化したものの活用方法を実装例(下記)と共に説明します。
@pytest.mark.normal
def test_execute_func(get_resetter_of_sys_modules, mocker):
module_setter = get_resetter_of_sys_modules
# キャッシュ済みのモジュールを削除し、対象のモジュールをモック化
module_setter(
remove_cached_modules=['src.target_module', 'src.sample_with_having_errors'],
mocker_modules=['disabled_module', 'cannot_use_package.cannot_use_module'],
)
# 期待値を設定
ret_y1 = 4
ret_y2 = 5
y_sum = ret_y1 + ret_y2
# 該当モジュールをモック化
import sys
disabled_module_mocker = sys.modules['disabled_module']
mocker.patch.object(disabled_module_mocker, 'undefined_function', return_value=ret_y1)
mocker.patch('src.sample_with_having_errors.disabled_function', return_value=ret_y2)
import src.sample_with_having_errors as swhe
estimate_y = swhe.execute(1)
assert estimate_y == y_sum
上記のうち、以下に示す部分が重要です。
# 期待値を設定
ret_y1 = 4
ret_y2 = 5
y_sum = ret_y1 + ret_y2
# 該当モジュールをモック化
import sys
disabled_module_mocker = sys.modules['disabled_module']
mocker.patch.object(disabled_module_mocker, 'undefined_function', return_value=ret_y1)
mocker.patch('src.sample_with_having_errors.disabled_function', return_value=ret_y2)
これらの処理を整理すると、以下のように大別できます。
モック化した後の処理パターン2つ
- import文によりモジュールを読み込む場合
sys.modules
にキャッシュされているモックインスタンスを取得する - from文によりモジュールを読み込む場合
従来通り、mocker.patch
を用いてpatchを当てる
上記に示したパターンに対し、それぞれの具体的な対応関係は、下記の図に示す通りです。


上記の処理を行うことで、execute
関数はエラーなく実行できるようになります。
pytest tests/test_target_module.py::test_execute_func
==================================================================================== test session starts ====================================================================================
platform linux -- Python 3.12.10, pytest-8.3.5, pluggy-1.6.0 -- /usr/local/bin/python3.12
cachedir: home/.cache
Using --randomly-seed=824814770
rootdir: /opt
configfile: pyproject.toml
plugins: env-1.1.5, randomly-3.16.0, mock-3.14.1, cov-6.1.1, anyio-4.9.0, asyncio-0.26.0
asyncio: mode=Mode.STRICT, asyncio_default_fixture_loop_scope=session, asyncio_default_test_loop_scope=session
collected 1 item
tests/test_target_module.py::test_execute_func PASSED [100%]
====================================================================================== tests coverage =======================================================================================
_____________________________________________________________________ coverage: platform linux, python 3.12.10-final-0 ______________________________________________________________________
Coverage HTML written to dir htmlcov
Coverage XML written to file coverage.xml
===================================================================================== 1 passed in 0.54s ====================================================================================
さらに、これらは同時にテストをしても、問題なく動作することを確認済みです。
pytest tests/test_target_module.py
==================================================================================== test session starts ====================================================================================
platform linux -- Python 3.12.10, pytest-8.3.5, pluggy-1.6.0 -- /usr/local/bin/python3.12
cachedir: home/.cache
Using --randomly-seed=3843431221
rootdir: /opt
configfile: pyproject.toml
plugins: env-1.1.5, randomly-3.16.0, mock-3.14.1, cov-6.1.1, anyio-4.9.0, asyncio-0.26.0
asyncio: mode=Mode.STRICT, asyncio_default_fixture_loop_scope=session, asyncio_default_test_loop_scope=session
collected 5 items
tests/test_target_module.py::test_cannot_load_specific_files PASSED [ 20%]
tests/test_target_module.py::test_avoid_raising_import_exception PASSED [ 40%]
tests/test_target_module.py::test_raise_import_exception_with_existing_file PASSED [ 60%]
tests/test_target_module.py::test_execute_func PASSED [ 80%]
tests/test_target_module.py::test_can_load_private_file PASSED [100%]
====================================================================================== tests coverage =======================================================================================
_____________________________________________________________________ coverage: platform linux, python 3.12.10-final-0 ______________________________________________________________________
Coverage HTML written to dir htmlcov
Coverage XML written to file coverage.xml
===================================================================================== 5 passed in 0.58s ====================================================================================
今回のまとめ
今回は、以下について解説しました。
今回の内容
かなり特殊なケースの事例かもしれませんが、ライブラリの有無やユーザ定義関数の有無で処理を分ける場合は、今回紹介したようなテスト方法が有効に機能すると考えています。
pytestでテストコードを実装する際に、上記のような困りごとがあれば参考にしてみてください。