Python

Python単体テスト入門 – あなたのコードの品質を向上させる方法 (pytest編)

Pythonでの単体テストを効率的に行うために、pytestというテストフレームワークを利用する方法を解説します。はじめてpytestを使う方でも、この記事を読めばPythonの単体テストがスムーズに行えるようになります。

pytestとは?

pytestは、Pythonの単体テストを効率的に行うためのテストフレームワークです。次のような特徴があります。

  • 見やすくわかりやすいテストコードが書ける
  • 自動でテスト関数を見つけて実行する
  • 豊富なプラグインが利用できる

テストフレームワークとは、テストコードの作成、実行、結果の表示などを効率的に行うためのツールです。

pytestを使った単体テストの基本

pytestを使った、Pythonの単体テストを行う方法を説明します。

pytestのインストール

pytestをインストールするには、次のコマンドを実行します。

pip install pytest

これで、pytestがインストールされ、使用できるようになります。

テストコードの作成

まず、テスト対象の関数があるファイルと同じディレクトリに、test_で始まる名前のファイルを作成します。例えば、calc.pyというファイルのテストコードを作成する場合、test_calc.pyという名前のファイルを作ります。

次に、test_で始まる関数を作成し、その中にテストコードを書きます。

例えば、次のようなcalc.pyがあるとします。

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

def subtract(a, b):
    return a - b

これに対するテストコードtest_calc.pyは、次のようになります。

from calc import add, subtract

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

def test_subtract():
    assert subtract(2, 1) == 1
    assert subtract(1, -1) == 2

テストの実行

テストを実行するには、次のコマンドを実行します。

pytest

実行結果が次のように表示され、テストが成功したことが確認できます。

========================= test session starts =========================
platform linux -- Python 3.8.5, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /path/to/your/project
plugins: ...
collected 2 items

test_calc.py ..                                                  [100%]

========================== 2 passed in 0.03s ==========================

pytestの便利な機能

pytestには、テストをより効率的に行うための便利な機能がいくつかあります。ここでは、代表的なものをいくつか紹介します。

フィクスチャ

テストで共通して使用するオブジェクトや状態を、フィクスチャ(fixture)を使って定義することができます。例えば、次のようなデータベース接続を行うdb.pyがあるとします。

class Database:
    def __init__(self):
        self.conn = None

    def connect(self, db_name):
        # DBへの接続処理

    def disconnect(self):
        # DBからの切断処理

    def query(self, sql):
        # SQLの実行処理

これに対するテストコードtest_db.pyで、フィクスチャを使ってデータベース接続を行うと次のようになります。

import pytest
from db import Database

@pytest.fixture
def db():
    db = Database()
    db.connect("test_db")
    yield db
    db.disconnect()

def test_query(db):
    result = db.query("SELECT * FROM users")
    assert result == ...

パラメータ化されたテスト

パラメータ化されたテストを使うことで、複数の入力値に対するテストを簡単に書くことができます。例えば、calc.pyadd関数に対するテストコードをパラメータ化すると、次のようになります。

import pytest
from calc import add

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

テストカバレッジの確認方法

テストカバレッジは、テストコードがどれだけの割合でプロダクトコードをカバーしているかを示す指標です。pytestでは、pytest-covというプラグインを使ってテストカバレッジを確認できます。

まず、pytest-covをインストールします。

pip install pytest-cov

次に、テストカバレッジを確認したい対象のディレクトリを指定して、pytestコマンドを実行します。

pytest --cov=my_project tests/

実行結果には、テストカバレッジの情報が表示されます。

========================= test session starts =========================
platform linux -- Python 3.8.5, pytest-6.2.5, py-1.10.0, pluggy-1.0.0
rootdir: /path/to/your/project
plugins: cov-2.12.1
collected 2 items

tests/test_calc.py ..                                           [100%]

----------- coverage: platform linux, python 3.8.5-final-0 -----------
Name                Stmts   Miss  Cover
---------------------------------------
my_project/calc.py      4      0   100%

========================== 2 passed in 0.03s ==========================

この例では、my_project/calc.pyのテストカバレッジが100%であることが確認できます。

テストカバレッジは、テストの品質を確認するための一つの指標ですが、100%のカバレッジがあってもバグがないことを保証するわけではありません。テストコードの質や網羅性を向上させることも重要です。

まとめ

今回は、pytestを使ったPythonの単体テストの方法について解説しました。

pytestの基本的な使い方や便利な機能を活用することで、効率的な単体テストが行えるようになります。テストを積極的に取り入れて、品質の高いコードを書くことを目指しましょう。

ABOUT ME
湖山 貴裕
はじめまして。 二児のお父さんプログラマーです。最近キャンプにも興味あり。夏には庭でキャンプしようともくろみ中。ボドゲ好き。チョコ好き。茶道経験者。 2012年大学卒業→IT企業就職 Java,VB.NET, C#, javascript等の企業向けシステム開発/主にバックエンドを担当/AWSを少しかじる→2020年フリーランスエンジニアへ転身 広島でAWS案件にて楽しく活動中