pytestを活用したテスト駆動開発 - 人工知能応用特論Ⅰ 第7回

7.8K Views

November 27, 25

スライド概要

東京農工大学大学院先進学際科学府の人工知能応用特論Ⅰの第7回資料です.

profile-image

東京農工大学工学部知能情報システム工学科・先進学際科学府 准教授

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

ダウンロード

関連スライド

各ページのテキスト
1.

2025年度 人工知能応用特論Ⅰ: 機械学習・データサイエンスのための プログラミング 第7回: pytestを使ったテストコードの書き方 東京農工大学大学院先進学際科学府 山田宏樹 1

2.

スケジュール 第1回:Gitの基礎 第2回:Git・GitHubの実践 第3回:Pythonの環境構築 第4回:Dev Containerによる開発環境の構築 第5回:Visual Studio Code (VS Code) を活用した開発 第6回:読みやすいPythonコードの書き方 第7回:pytestを使ったテストコードの書き方 第8回:機械学習のプロジェクトにおける実験管理 スケジュールはあくまで暫定的なものです 2

3.

今回の授業の目標 pytestを活用したテスト駆動開発を学ぶ 研究開発では「新しいアルゴリズムの発明」や「データ解析そのもの」が目的に なりがちで,「プログラムが正しく動くかを検証する」という意識が薄くなりがち です.テストコードを書いて検証する方法論を学び,コードの品質・信頼性を向 上させましょう.テストコードを書くのをめんどくさがると,プログラムにバグ を埋め込みやすくなり,結局デバッグに時間を要して全体の開発時間が長くなる ということも多いにあります. 3

4.

実行環境 今回の講義で使うツールは以下の通り Visual Studio Code (VS Code) uv pytest (uvでインストールできます) 講義の課題で,上記のインストールは完了していると思います. 4

5.

目次 1. テストコードを書く意義 研究における実装のサイクル 研究におけるデバッグ テストコードで何ができる? 2. pytestを使ったテストコードの書き方 基本の使い方 フィクスチャ パラメータ化 5

6.

1. テストコードを書く意義 6

7.

研究におけるコーディング 研究においてどのようにコーディングをすれば効率的に実験を進めることができ るでしょうか?東京科学大学の岡崎直観先生が公開している,研究におけるコー ディングの極意についての資料が参考になります. NLP2013 チュートリアル資料: 研究者流コーディングの極意 上記資料の「3. 自分を過信せず検証せよ」と「4. 常に検証に備えよ」より抜粋 コードを少し書いては動作チェックというプロセスを繰り返すことで,プロ グラムを大きくしていく 大量のデータで動作させる前に,少量のデータで素早くプログラムを動か し,検証する 検証が億劫にならないように工夫せよ デバッグ・検証には時間がかかる この検証において有効なのがテストコードを書くことです 7

8.

研究におけるデバッグ デバッグ作業は開発時間の多くの部分を占めます.なので,どのようにデバッグ するべきかを知れば,開発効率を向上させることができます.デバッグの心得を 知るためには,以下の慶應義塾大学の渡辺宙志先生の資料が参考になります. デバッグの話 / Debugging for Beginners 上記資料より抜粋 デバッグは進捗ではない 結局は自分が入れたバグを自分でとる作業(マッチポンプ) デバッグの基本哲学 頭を使わない: なるべく機械的にチェックできる仕組みを作る 安全地帯を作る: 「ここまでは大丈夫」という砦を築きながら進む デバッグで最も重要なこと バグの原因を究明すること そもそもバグを入れないこと デバッグにおいても鍵を握るのがテストコードを書くことです 8

9.

研究における実装サイクル ここまでに説明した実装のサイクルで重要なこと コードを少し書いては動作チェックというプロセスを繰り返す 検証が億劫にならないように工夫 / 機械的にチェックできる仕組みを作る 安全地帯を作る: 「ここまでは大丈夫」という砦を築きながら進む これらを満たした開発サイクルの一つが,第5回講義で扱ったGitHub flow です. 再掲: GitHub flowに基づくワークフロー 基本方針 と feature の2種類のブランチを運用 main ブランチでは動作確認ずみで安定状態のバージョンを管理 開発はすべて main から派生した feature ブランチで行う main では開発を行わず, feature ブランチをマージして機能を追加する main 9

10.

1. Featureブランチを作る Featureブランチの名前は,そのブランチで何の作業を行なっているかがわかるよ うなものにしましょう.ここでは例として,data loaderを実装するために, add_dataloader という名前のfeatureブランチを作ってみましょう. git switch -c add_dataloader は「create」の意味しており,新しくブランチを作成して自動でそのブランチ に切り替えます. -c main main feature add_dataloader 10

11.

2. Featureブランチで作業を進める Featureブランチでdata loaderの実装をすすめ,適宜コミットしましょう.また, 下記コードを実行すると,リモートリポジトリに add_dataloader ができ,バッ クアップを取ることができます. git push -u origin add_dataloader 初回のみ -u をつけ,上流ブランチの設定をしましょう.次回以降は単に git push でOKです. 作業が完了したら,テストをして追加した機能が正しく動作するか検証します テストにより,バグを埋め込んでいないかを確認します. main main feature ・・・ add_dataloader 11

12.

3. (複数人で開発をしている場合) pull requestを作成する 個人開発の場合,この作業は必須ではありません 1. コードに加えた変更に関して,コラボレーター (先輩,指導教員,共同研究 者など)にフィードバックを依頼するpull requestを作成します. 2. レビュー担当者は質問,コメント,提案を残します. 本講義では,これ以上pull requestとレビューについて踏み込みませんが,以下の 資料が参考になります. GitHub Docs: pull requestを作成 GitHub公式サイトでpull requestの作成方法が説明されています GitHub Docs: pull requestでの変更をレビューする GitHub公式サイトでpull requestでの変更をレビューする方法が説明されています CyberAgent AI Lab研修 / チーム開発から学ぶコードレビューのお作法 CyberAgentのAI Labの研修資料が公開されています.コードレビューのお作法や ベストプラクティスがまとまっているので,チーム開発をする人は必見です ※ 12

13.

4. Featureブランチをマージする Squash mergeによるfeatureブランチの統合 Squash mergeは以下のように実行できます. git switch main git merge --squash add_dataloader git commit により,現在のブランチとmerge対象のブランチの差分が 一つにまとめられ,ステージングされた状態となります.ステージングまでしか されないので忘れずに git commit をする必要があります. git merge --squash main main feature main git merge --squash add_dataloader git commit 変更を⼀つにまとめる ・・・ ・・・ add_dataloader add_dataloader 13

14.

5. Featureブランチを削除する ここでは,squash mergeをした前提で話を進めます.GitHub flowではfeatureブ ランチをマージ後には,featureブランチを削除することが多いです.これは,た くさんのブランチが履歴に残ったままだと混乱を引き起こす原因となるためで す.以下のようにしてブランチを削除します. git branch -D add_dataloader Squash mergeをした場合だと,featureブランチを削除すれば,そこで作られたコ ミットはログで表示されなくなります, git branch –D add_dataloader main main この部分は内部的には保存されたままだが, 到達不能コミットとなりログで表⽰されなくなる ・・・ ・・・ add_dataloader 到達不能コミットはどのブランチからも 辿れないコミットのことを指す.⼀定期間経過すると, 到達不能コミットは gitのガベージコレクションにより消去される. 14

15.

GitHub flowでは手順1-5のサイクルをまわし,実装を進める コードを少し書いては動作チェックというプロセスを繰り返す → Featureブランチでの作業 検証が億劫にならないように工夫 / 機械的にチェックできる仕組みを作る → mergeする前にテストコードを作成し,正しく実装されているか検証 安全地帯を作る: 「ここまでは大丈夫」という砦を築きながら進む → mergeされる前に検証を行っているので, main にはデバッグ済みの状態が 登録される.安全地帯が作られているので,バグの発生原因を特定しやすい 15

16.

テストコードを書くメリット 実行確認のしやすさ テストコードを普段書かない人であっても,書き捨てのコードで実行確認をして いるのではないでしょうか?その書き捨てのコードをテストコードにしておけ ば,GitHubで管理して使い回すこともできます. コードの修正時に発生したバグの検知 テストコードを自動で実行するように設定しておけば,リファクタリングやコー ド修正により発生したバグを検知できるようになります. 再現性の担保 リポジトリにテストコードが含まれていると,他人がそのまま動かしやすく,動 かなくてもどこが悪いのかがすぐにわかるようになります.また,テストコード にはテストしたい対象の入出力関係が記述されているので,初めてコードを読む 人でも,どのような使用が想定されているかがわかりやすくなります. 16

17.

どの程度テストを書くべきか? 研究プロジェクトでは試行錯誤を素早く繰り返す必要があるので,一般的なソフ トウェア開発のように100%の網羅率 (カバレッジ) を目指す必要はありません. テストした方が良いもの featureブランチで追加したメインの機能 テストを書かないとバグの検知が難しい処理 実装時の動作に確信がもてない処理 複雑な条件分岐や境界値など例外が発生しそうな箇所 17

18.

2. pytestを使ったテストコードの書き方 18

19.

pytestとは? Pythonでテストコードを書くときに使うツールが pytest です.Pythonの標準ラ イブラリに unittest というものがありますが, unittest よりも pytest の方が 書きやすく,拡張性も高いので pytest の方が広く使われてる印象です. unittest の例 import unittest class TestSomething(unittest.TestCase): def test_add(self): self.assertEqual(add(1, 2), 3) pytest の例 def test_add(): assert add(1, 2) == 3 は unittest のようにクラスを書かなくてよく,Pythonに標準で組み込 19 まれている assert 文を使いテストの成否を判断します. pytest

20.

演習: とりあえず pytest を使ってみよう pytest を使う準備をする まず, uv を使って演習用のプロジェクトを作りましょう. uv init --package lecture_pytest 作ったプロジェクトに移動し, pytest をインストールする cd lecture_pytest uv add --dev pytest で --dev オプションをつけると,開発用の依存パッケージとしてインス トールすることができます. uv add 20

21.

pytest を実行する テストの成功例 プロジェクトのルートディレクトリに tests というディレクトリを作り,以下の test_one.py というファイルを作ってください. def test_passing(): assert (1, 2, 3) == (1, 2, 3) プロジェクトのルートディレクトリで pytest を実行します.( pytest は uv でイ ンストールしているので,実行には uv run を使います) uv run pytest tests/test_one.py 21

22.

実行結果 yamadakoki@MacBook-Pro-2021 lecture_pytest % uv run pytest ============================ test session starts ============================ platform darwin -- Python 3.12.10, pytest-9.0.1, pluggy-1.6.0 rootdir: /Users/yamadakoki/codes/lecture_pytest configfile: pyproject.toml collected 1 item tests/test_one.py . [100%] ============================= 1 passed in 0.00s ============================= tests/test_one.py します. の後ろの . は,テストが実行され成功 (Pass) したことを表 テストの失敗例 次に,テストが失敗したときにどうなるのか見てみましょう.プロジェクトのル ートディレクトリの tests の中に,以下の test_two.py というファイルを作り, uv run pytest tests/test_two.py を実行してください. def test_failing(): assert (1, 2, 3) == (3, 2, 1) 22

23.

実行結果 yamadakoki@MacBook-Pro-2021 lecture_pytest % uv run pytest tests/test_two.py ============================ test session starts ============================ platform darwin -- Python 3.12.10, pytest-9.0.1, pluggy-1.6.0 rootdir: /Users/yamadakoki/codes/lecture_pytest configfile: pyproject.toml collected 1 item tests/test_two.py F [100%] ================================= FAILURES ================================== _______________________________ test_failing ________________________________ > E E E E def test_failing(): assert (1, 2, 3) == (3, 2, 1) assert (1, 2, 3) == (3, 2, 1) At index 0 diff: 1 != 3 Use -v to get more diff tests/test_two.py:2: AssertionError ========================== short test summary info ========================== FAILED tests/test_two.py::test_failing - assert (1, 2, 3) == (3, 2, 1) ============================= 1 failed in 0.03s ============================= の後ろの F はテストが失敗したことを表します.テストが失 敗すると,エラーが発生した場所とその周囲のコードが表示されます.このセク 23 ションのことをトレースバック (traceback) と呼びます. tests/test_two.py

24.

pytest pytest の基本 の実行方法 pytest 引数を指定しない場合は,ローカルディレクトリとサブディレクトリでテストを 検索し,実行します. ファイル名> pytest < 指定されたファイルに含まれているテストを実行します. pytest <ファイル名> < ファイル名> ... とすることで複数のファイルも指定可能です. ディレクトリ名> pytest < 指定された一つ,または複数のディレクトリでテストを再帰的に検索し,実行し ます. 24

25.

テストディスカバリ は次の命名規則にしたがってテストコードを検索しています. テストファイルの名前は test_<something>.py ,または <something>_test.py という形式で記述する テストメソッド,テスト関数は test_<something> という形式で記述する テストクラスの名前は Test<Something> という形式で記述する 上記の規則に則ってないとテストコードとして検知されません. pytest テストの結果 実行結果で見たように,ファイル名の後にテスト結果が表示されます. PASSED . : テストが正常に完了したことを表す FAILED F : テストが正常に完了しなかったことを表す ERROR E : 例外がテスト関数の実行中ではなく,フィクスチャ (後述) 等の 実行中に発生したことを表す 他にも,SKIPPED s , XFAIL x , XPASS X などがありますが,各自で調べること 25

26.

pytest でテスト関数を作る テスト関数を書くときに,テストが失敗したことを伝える基本の手段は assert 文を使うことです. assert 文 では, assert <式> で任意の式を使うことができます. bool 値に変換さ れる式が False と判定された場合,そのテストが失敗したことが伝えられます. pytest はPython標準の assert のログを,よりわかりやすくアサーションが失 敗した理由を説明するログに置き換えてくれます. pytest pytest.fail() 文以外にも pytest.fail() を使って,テストが失敗したことを伝えるこ とが可能です.複雑なアサーションチェックの作成のためにアサーションヘルパ ー関数を作るときには pytest.fail() を使う方が便利な場合があります.基本的 に assert 文で書けるなら assert 文を使う方が良いです. assert 26

27.

演習: 自作のライブラリをインポートして,テストを行う 自作のライブラリを用意する 先ほどの演習で作ったプロジェクトの src/lecture_pytest に以下の image_filters.py を作ってください. import numpy as np from scipy.ndimage import gaussian_filter def normalize(img: np.ndarray) -> np.ndarray: """ Normalize image values to [0, 1]. """ img_min = img.min() img_max = img.max() if img_max == img_min: return np.zeros_like(img) return (img - img_min) / (img_max - img_min) def blur(img: np.ndarray, sigma: float = 1.0) -> np.ndarray: """ Apply Gaussian blur to a 2D image. """ return gaussian_filter(img, sigma=sigma) 27

28.

必要なライブラリをインストールする 先ほど用意した image_filters.py には numpy と scipy が必要なので,これらを インストールしましょう. uv add numpy scipy テストコードを用意する プロジェクトの tests ディレクトリの中に,以下の test_image_filters を作っ てください. 28

29.

import numpy as np from lecture_pytest.image_filters import normalize, blur def test_normalize_range(): # ダミー画像を作成 img = np.array([[0, 50], [100, 150]], dtype=float) norm = normalize(img) # 正規化レンジの確認 assert norm.min() == 0.0 assert norm.max() == 1.0 def test_blur_smooths_image(): img = np.zeros((32, 32)) img[16, 16] = 1.0 # インパルス blurred = blur(img, sigma=1.0) # ぼかし結果はピークが小さくなる assert blurred[16, 16] < 1.0 # 周囲には非ゼロ値が広がるはず assert blurred[15, 16] > 0.0 assert blurred[17, 16] > 0.0 29

30.

実行結果 yamadakoki@MacBook-Pro-2021 lecture_pytest % uv run pytest tests/test_image_filters.py ============================ test session starts ============================ platform darwin -- Python 3.12.10, pytest-9.0.1, pluggy-1.6.0 rootdir: /Users/yamadakoki/codes/lecture_pytest configfile: pyproject.toml collected 2 items tests/test_image_filters.py .. [100%] ============================= 2 passed in 5.40s ============================= 30

31.

想定される例外をテストする テストしているコードで,想定されている例外をテストするには, pytest.raises() を使います. with pytest.raises(< 例外クラス>) 文 次のコードブロックの何かが <例外クラス> を発生させるはずであることを意味し ます.この例外が発生しない場合,テストは失敗します. <例外クラス> としてよく用いられるもの: TypeError : 引数の型が不正 ValueError : 値が不正 (範囲外・負の値は不可など) IndexError : 配列のインデックス範囲外の参照エラー 他の例外もたくさんあるので,Pythonの組み込み例外を参考に各自調べること 外部ライブラリが提供している例外も <例外クラス> として設定することも可能. (例えば, numpy の numpy.linalg.LinAlgError など) 31

32.
[beta]
演習: 想定される例外をテストする

先ほど使った blur 関数を, sigma に0より小さい値が設定されると ValueError
を出すように修正します.
def blur(img: np.ndarray, sigma: float = 1.0) -> np.ndarray:
"""
Apply Gaussian blur to a 2D image.
"""
if sigma <= 0:
raise ValueError("sigma must be > 0")
return gaussian_filter(img, sigma=sigma)

先ほど使った test_image_filters に import pytest を追加した上で,以下のテ
スト関数を追加してください.
def test_blur_raises_for_nonpositive_sigma():
img = np.ones((16, 16))
with pytest.raises(ValueError):
blur(img, sigma=0)
with pytest.raises(ValueError):
blur(img, sigma=-1.0)

32

33.

実行結果 yamadakoki@MacBook-Pro-2021 lecture_pytest % uv run pytest tests/test_image_filters.py =================================================== test session starts =================================================== platform darwin -- Python 3.12.10, pytest-9.0.1, pluggy-1.6.0 rootdir: /Users/yamadakoki/codes/lecture_pytest configfile: pyproject.toml collected 3 items tests/test_image_filters.py ... [100%] ==================================================== 3 passed in 0.25s ==================================================== 33

34.

テスト関数を構造化する テストコードはArrange–Act–Assert,あるいはGiven–When–Thenのように3つ のステージに分けることがベストプラクティスとされています.この分割によ り,テストは「何かを行う準備をする」,「何かを実行する」,「うまくいったかを 検証する」に分けられ,実際に何をテストしているのかが明確になります.特 に,アサーションはテスト関数の最後に配置するように意識しましょう. Arrange / Given アクションを実行するために,データまたは環境を整えます. Act / When あるアクションを実行します.この実行が正しいかどうかを検証することがテス トの焦点となります. Assert / Then アクションの結果が期待通りに実行されているかを,アサーション等を使って検 証します. 34

35.

pytest のフィクスチャ (fixture) のフィクスチャとは,テスト関数の実行前(あるいは実行後)に pytest が実行する関数のことです. pytest どういった時に使われるか? 前のページで説明したArrange / Givenの処理,つまりデータセットや環境を 整える前処理.このような前処理をセットアップと呼びます. 複数のテストで使うデータを準備することもできる テストコードを実行後にしたい後処理(例えばテストに使用した一時ファイ ルの削除など).このような後処理をティアダウン (Teardown) と呼びます. 35

36.

単純なフィクスチャの使用例 import pytest @pytest.fixture() def sample_data(): return [1, 2, 3, 4, 5] def test_sample_data_length(sample_data): assert len(sample_data) == 5 はその関数がフィクスチャであることを pytest に認識させ るための修飾子 (マーカー) です.テスト関数の引数にフィクスチャの名前を入力 すると,そのテストを実行する前にそのフィクスチャが実行されます.また,そ のテスト関数にデータを返すことも可能です. フィクスチャには様々な機能があるので,次の演習で具体的にどういったことが できるのかを確認しましょう. @pytest.fixture() 36

37.
[beta]
演習: フィクスチャの活用例
test_image_filters

に以下を追記しましょう.

@pytest.fixture
def temporary_image_file(tmp_path):
# --- セットアップ --file_path = tmp_path / "temp_image.npy"
img = np.zeros((32, 32))
img[16, 16] = 1.0 # インパルス
np.save(file_path, img)
# yield を挟むことで、ここまでが「セットアップ」
yield file_path
# --- ティアダウン --if file_path.exists():
file_path.unlink()

# ファイル削除

def test_blur_load_image(temporary_image_file):
img = np.load(temporary_image_file)
blurred = blur(img, sigma=1.0)
assert blurred[16, 16] < 1.0
assert blurred[15, 16] > 0.0

37

38.

前のページの temporary_image_file は,セットアップでテストで使うための画 像を一時ファイルをとして作り,ティアダウンでその一時ファイルを削除するフ ィクスチャです.一つずつ使われている機能を見ていきましょう. pytestの組み込みフィクスチャ は標準で搭載しているフィクスチャ (組み込みフィクスチャ) を持ってい ます. tmp_path もその組み込みフィクスチャの一つです.(他の組み込みフィク スチャについてはpytest fixtures: explicit, modular, scalableを参照) tmp_path : テストごとに固有の一時ディレクトリを pathlib.Path 形式で提供します.テス トごとに異なるディレクトリが作られるので,二つのテストで競合する心配はあ りません.テスト終了後に一時ディレクトリは自動で削除されます. (補足: 今回は例を示すために,ティアダウンで画像を削除していますが, tmp_path で作った一時ディレクトリは自動で削除されるので,本当は画像を削 除するティアダウンは必要ありません.) pytest 38

39.

ティアダウン ティアダウン (後処理) を実装するためには yield というPythonの標準機能を使い ます.これは,処理やデータをジェネレータの呼び出し元へ渡すことができま す.今回の例だと, yield file_path までのコードがセットアップ(前処理)に 対応し, file_path をテストに渡します.テストが終了したら yield file_path 以降の処理が実行され,作られた画像の一時ファイルが削除されます. 39

40.

パラメータ化 テストのパラメータ化とは,テスト関数にパラメータを追加することで,異なる 入力のパターンを検証するための枠組みです.パラメータ化をすることで,いろ んな入力パターンのテストをシンプルに記述できるようになります. パラメータ化の種類 関数をパラメータ化する: @pytest.mark.parametrize フィクスチャをパラメータ化する: @pytest.fixture(params=[...]) フック関数を使ったパラメータ化: pytest_generate_tests 40

41.

関数をパラメータ化する 同じテスト関数を異なる入力値で実行したいときには, @pytest.mark.parametrize を使います. 構文 @pytest.mark.parametrize( "引数1, 引数2, ...", [ (値1, 値2, ...), (値A, 値B, ...), ] ) 41

42.

使用例 @pytest.mark.parametrize( "x, y, expected", [ (2, 3, 5), # 2 + 3 = 5 (10, 5, 15), # 10 + 5 = 15 (-1, 1, 0), # -1 + 1 = 0 ] ) def test_addition(x, y, expected): assert x + y == expected 引数 (x, y, expected) に対して, (2, 3, 5) , (10, 5 , 15) , (-1, 1, 0) の 3通りの入力で, test_addition を実行します. 実行例 先ほどの使用例を test/test_parametrize.py として保存し, pytest を実行 yamadakoki@MacBook-Pro-2021 lecture_pytest % uv run pytest tests/test_parametrize.py ======================================================================= test session starts ======================================================================= platform darwin -- Python 3.12.10, pytest-9.0.1, pluggy-1.6.0 rootdir: /Users/yamadakoki/codes/lecture_pytest configfile: pyproject.toml collected 3 items tests/test_parametrize.py ... [100%] ======================================================================== 3 passed in 0.00s ======================================================================== 42

43.

フィクスチャをパラメータ化する 同じテストに対して,異なるセットアップをしたいときに @pytest.fixture(params=...) を使います. 使用例 @pytest.fixture(params=[1, 2, 3]) def number(request): return request.param def test_number_is_positive(number): assert number > 0 テスト関数 test_number_is_positive が入力 1 , 2 , 3 の3通りで実行されます. request は pytest の組み込みフィクスチャです. @pytest.fixture の引数 params で指定された入力が request.param に格納されます. 43

44.

フック関数を使ってパラメータ化する 動的にテストパラメータを生成したい場合には pytest_generate_tests を使いま す.パラメータがコード実行時に決まる場合やテストが外部情報に依存する場合 に活躍します. pytest_generate_tests が実行される流れ 1. pytest がテストファイルを読み込む(収集/collection) 2. 各テスト関数に対して pytest_generate_tests(metafunc) を呼ぶ 3. pytest_generate_tests の中で metafunc.parametrize(...) を呼ぶと、 そのテスト関数に対するパラメータセットが追加される 4. 最終的に pytest が生成したパラメータ分だけテストノード (実行単位) を作る 44

45.

使用例: ディレクトリ内の全ての画像をテストする import pathlib def pytest_generate_tests(metafunc): if "image_file" in metafunc.fixturenames: image_dir = pathlib.Path("tests/test_images/") image_files = list(image_dir.glob("*.png")) metafunc.parametrize("image_file", image_files) def test_image_processing(image_file): img = load_image(image_file) # 例 out = process_image(img) assert out is not None : そのテスト関数が要求するフィクスチャ名のリス ト (例:["tmp_path", "image_data"]).これを見て「どのテストにパラメータ を与えるべきか」を判定するのが典型 metafunc.parametrize(argnames, argvalues) : argnames : "a,b" あるいは ["a","b"] のように引数名を指定 argvalues : argnames で指定した引数名に対応する値リスト (タプル等) metafunc.fixturenames 45

46.

実践的な pytest の使い方 46

47.

VS Code で pytest を使う VS Codeで pytest を活用するときには,以下のVS Codeの公式ドキュメントを参 考にしましょう.Python公式の拡張機能があれば使えます. Python testing in Visual Studio Code VS CodeのTestingビュー (フラスコのアイコン) からテストコードを実行したり, デバッグモードで実行することも可能です. 47

48.

pytest でスモークテストをする を使ってスモークテスト (動作確認をするための最小限のテスト) をする ことで,実験設計を明確にすることができます. pytest で実験コードを書く方 法は以下の資料を参考にしましょう! [堅牢.py #1] テストを書かない研究者に送る、最初にテストを書く実験コード入門 pytest 48

49.

参考資料 B. Okken, テスト駆動Python 第2版,翔泳社 pytestの使い方が網羅的に載っています.pytestを使いこなしたい人は読みましょ う! Sansan Tech Blog: 2023年 研究開発部 新卒技術研修 ~ テストコード編 ~ pytestを使ったテストコードの書き方や実践方法がよくまとまっています. 49

50.

課題 課題内容 本講義で扱っていない pytest の組み込みフィクスチャを一つを調べ,使用例を まとめてください.ファイル名は 学籍番号_名前_pytest としてください.また, ファイル形式は pdf にしてください. 注意事項 ファイル名と拡張子が正しいか確認すること. 締め切り 日本標準時で次回講義の前日の23:59まで 50

51.

ここまで資料をご覧になっていただきありがとうございます. 資料に間違いがあったり,より良いベストプラクティスがある 場合はご連絡ください.次回以降の講義にフィードバックを活 かします. Twitter: @KokiYamada6 本講義は,学習コストと得られる恩恵のバランスをとっています.より良いベス トプラクティスがあったとしても,学習コストの理由により採用しない場合があ ります.その点についてご了承ください. 51