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?

Pytestのはじめかた【前編】完全初心者向け:テストを書いたことがない人でも5分でわかる

1
Posted at

シリーズ構成

この記事は2部構成です。

記事 内容
前編(本記事) 基本・assert・pytest.raises・parametrize・カバレッジ
後編 fixture・モック

まずはこの前編で基本を身につけてから、後編に進むのがおすすめです。


はじめに

「テストコードって何?なんで必要なの?」というところから始めて、実際にPytestでテストを書いて動かすところまでを丁寧に解説します。

難しいことは一切なし。Pythonが少し書けるなら大丈夫です。


テストって何?なんで書くの?

テストとは、「自分のコードが期待どおりに動くかを自動で確認する仕組み」 です。

たとえば「1 + 1 を計算する関数を作ったとして、本当に2が返ってくるか?」を自動でチェックしてくれます。

手動で動作確認するのと何が違うの?

手動確認 テストコード
毎回自分で実行して目で確認 コマンド一発で全部まとめてチェック
変更のたびに全部やり直し 何度でも瞬時に繰り返せる
確認漏れが起きやすい 網羅的に確認できる

Pytestとは?

pytest はPythonで最もよく使われるテストフレームワークです。

  • シンプルで書きやすい
  • 公式の unittest より直感的
  • 業務でも個人開発でも広く使われている標準的な選択肢

インストール

pip install pytest

インストールできたか確認:

pytest --version

pytest 8.x.x のようなバージョンが表示されればOKです。


まず動かしてみる

Step 1: テスト対象の関数を作る

calculator.py というファイルを作ります。

# calculator.py

def add(a, b):
    return a + b

Step 2: テストファイルを作る

test_calculator.py というファイルを作ります。

# test_calculator.py

from calculator import add

def test_add():
    result = add(1, 2)
    assert result == 3

ポイントが3つあります:

  1. ファイル名は test_ で始める → Pytestが自動で見つけてくれます
  2. 関数名も test_ で始める → テスト対象として認識されます
  3. assert で期待値と比較する → 一致しなければテスト失敗

Step 3: テストを実行する

pytest

こんな結果が表示されれば成功です:

========================= test session starts ==========================
collected 1 item

test_calculator.py .                                             [100%]

========================== 1 passed in 0.01s ===========================

🎉 テストが通りました!


assert の基本

テストの肝は assert 文です。

assert 1 + 1 == 2          # OK(True)
assert "hello"[0] == "h"   # OK(True)
assert [1, 2, 3][1] == 2   # OK(True)

assert 1 + 1 == 3          # NG → テスト失敗になる

assert 期待する条件 と書くだけ。条件がFalseになったときにテスト失敗と判定されます。


テストが失敗したときはどう見える?

わざと失敗させてみましょう。

def test_add_wrong():
    result = add(1, 2)
    assert result == 999  # わざと間違えた

実行すると:

FAILED test_calculator.py::test_add_wrong - AssertionError: assert 3 == 999

どのファイルの・どの関数で・何が違ったかが一目でわかります。


複数のテストをまとめて書く

テスト関数はいくつでも書けます。

# test_calculator.py

from calculator import add

def test_add_positive():
    assert add(1, 2) == 3

def test_add_negative():
    assert add(-1, -2) == -3

def test_add_zero():
    assert add(0, 5) == 5

pytest を実行すると、全部まとめてチェックしてくれます:

test_calculator.py ...    [100%]
3 passed in 0.01s

よく使うオプション

# 詳細を表示(どのテストが通ったか一覧で見たい)
pytest -v

# 特定のファイルだけ実行
pytest test_calculator.py

# テスト名を指定して実行
pytest test_calculator.py::test_add_positive

ファイル構成の例

小さなプロジェクトならこれで十分です:

my_project/
├── calculator.py       # テスト対象のコード
└── test_calculator.py  # テストコード

大きくなってきたら:

my_project/
├── src/
│   └── calculator.py
└── tests/
    └── test_calculator.py

Note: src/ 以下にコードを置く構成では、from calculator import add がそのままでは動きません。プロジェクトルートに conftest.py を置くか、PYTHONPATH=src pytest のように環境変数を設定してください。


ステップアップ①:例外をテストする(pytest.raises)

「この入力のときはエラーになるはず」という動作もテストできます。

たとえば calculator.py に割り算関数を追加します:

# calculator.py

def divide(a, b):
    if b == 0:
        raise ValueError("0で割ることはできません")
    return a / b

ゼロ除算のときに ValueError が発生することをテストするには:

# test_calculator.py

import pytest
from calculator import divide

def test_divide_by_zero():
    with pytest.raises(ValueError):
        divide(10, 0)

with pytest.raises(例外の種類): のブロック内で指定の例外が発生すれば、テスト成功です。

エラーメッセージの内容まで確認したい場合:

def test_divide_by_zero_message():
    with pytest.raises(ValueError, match="0で割ること"):
        divide(10, 0)

match= には正規表現パターンを指定します。指定したパターンがエラーメッセージに含まれていればテスト成功です("0で割ること" は正規表現としても機能します)。


ステップアップ②:複数パターンをまとめてテストする(@pytest.mark.parametrize)

同じ関数に対して「入力と期待値の組み合わせ」を複数試したいとき、テスト関数を何個も書くのは冗長です。

@pytest.mark.parametrize を使うとすっきり書けます:

import pytest
from calculator import add

@pytest.mark.parametrize("a, b, expected", [
    (1, 2, 3),
    (-1, -2, -3),
    (0, 5, 5),
    (100, -100, 0),
])
def test_add(a, b, expected):
    assert add(a, b) == expected

実行すると、4パターンが個別のテストとして実行されます:

test_calculator.py::test_add[1-2-3] PASSED
test_calculator.py::test_add[-1--2--3] PASSED
test_calculator.py::test_add[0-5-5] PASSED
test_calculator.py::test_add[100--100-0] PASSED

1つ失敗しても、どのパターンで失敗したかが一目でわかります。


ステップアップ③:カバレッジを計測する(pytest-cov)

カバレッジとは、「テストによってコードの何%が実行されたか」を示す指標です。カバレッジが低い=テストできていない箇所が多い、ということを意味します。

インストール

pip install pytest-cov

実行方法

pytest --cov=calculator

出力例:

---------- coverage: platform linux, python 3.11 ----------
Name             Stmts   Miss  Cover
------------------------------------
calculator.py        6      1    83%
------------------------------------
TOTAL                6      1    83%

Miss の列が「テストされていない行数」、Cover が「カバレッジ率」です。

どの行がテストされていないか確認する

pytest --cov=calculator --cov-report=term-missing
Name             Stmts   Miss  Cover   Missing
----------------------------------------------
calculator.py        6      1    83%   12

Missing の列に行番号が表示されます。その行を見てテストを追加するかどうか判断できます。

カバレッジの目安

100%を目指す必要はありません。重要なのは**「テストされていない箇所を把握すること」**です。

カバレッジ 目安
〜50% テストが少ない。重要な関数から優先的に追加
70〜80% 多くのプロジェクトで現実的な目標ライン
90%以上 かなり手厚い状態。維持コストとのバランスを意識

まとめ

やること 方法
インストール pip install pytest
テストファイルを作る ファイル名を test_ で始める
テスト関数を書く 関数名を test_ で始め、assert で確認
テストを実行する pytest
例外をテストする pytest.raises
複数パターンをテストする @pytest.mark.parametrize
カバレッジを確認する pip install pytest-cov → pytest --cov

まずは基本の assert から始めて、慣れてきたら parametrize でテストを整理し、pytest-cov でカバレッジを確認するという流れがおすすめです。


さらに先へ

  • fixture → テストの前準備(DBの初期化など)を共通化する
  • モック(unittest.mock)→ 外部APIやファイルI/Oを擬似的に差し替える
  • CI連携 → GitHub ActionsなどでPushのたびに自動テストを走らせる
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?