pytest

【pytest】Pythonプログラムをpytestでテストする方法

【pytest】Pythonプログラムをpytestでテストする方法
naoki-hn

Python プログラムのテストを実行するためのフレームワークである pytest モジュールについて解説します。

pytest とは

pytest とは、Python のテストフレームワークです。

テスト駆動開発 (TDD:Test-Driven Development) という自動テストを中心にした高品質のソフトウェア開発をするための方法論があり、Python コミュニティでは幅広く利用されています。テスト駆動開発においては pytest のようなテストフレームワークは非常に重要です。テスト駆動開発は「エキスパートPythonプログラミング」という書籍にも記載があるため、参考にしてもらえるとよいかと思います。

さて、Python 標準のテストフレームワークとしては unittest モジュールがありますが、機能制限などに不満を持つ人たちが出てきました。それらの開発者によって開発されたテストフレームワークの 1 つが pytest です。他にもテスト用のモジュールはいくつか存在します。

pytest は「Python Software Foundation」と「JetBrains PyCharm」 が共同で実施している Python 開発者アンケートにおいて「ユニットテストフレームワーク」項目で50%以上の回答となっています。このことから広く使われているテストフレームワークであると言えます。pytest は Python のテストフレームワークとして学ぶ意味があるモジュールです。

この記事では、pytest を使用したテストの基本について紹介していきます。

Python 標準の unittest の使い方は「Pythonプログラムをunittestでテストする方法」を参考にしてください。

pytest の使い方

プログラムのテストのイメージに慣れていない方のために、まずは以下の図を使って簡単なテストイメージを紹介します。以降で具体的なプログラムも使って説明をしていきますので、ここではまずイメージをつかんでください。

pytestのイメージ

sample.py というプログラムを作成しテストしたいと考えているとします。このsample.py には Sample というクラスがあり xy を足して 2 倍にするだけのシンプルな add_and_double というメソッドが定義されています。

このプログラムをテストしたい場合には「test_sample.py」というようなテストプログラムを作成します。テストプログラム内では sample をインポートして sample 内のクラス Sample を生成してメソッド add_and_double を呼び出して使用しています。

pytest では「test」で始まるファイル名をテストプログラムと認識します。また、該当するテストプログラムファイル内で以下に一致するものをテスト対象と判断します。

  • Test から始まるクラス
  • test から始まるモジュール関数

なお、大文字小文字を区別しますので「test から始まるクラス」や「Test から始まる関数」は作らないように注意しましょう。

各テストプログラム内では「assert temp.add_and_double(1, 1) == 4」のようにテスト対象モジュールの返却値などに対する判定を「assert」を使って記述します。この判定式の結果が一致しない場合にはテスト失敗となります。

上記例では x=1, y=1として引数を渡していますので (1 + 1) × 2 =4 を add_and_double メソッドは返却してほしいわけですが、異なる値が返ってくるということはメソッドの処理に何か問題があるということになります。なお、assert は 1 つの関数やメソッドに複数行でも書くことができます。

テストプログラム内にて、テスト観点毎にテストを実行する関数やクラスのメソッドをどんどん追加していくわけです。pytest を実行するとテストプログラム内に定義されているテスト用関数やメソッドが順番に実行されていき、それぞれが成功したか失敗したかを出力してくれます。

まずはテストに関して上記のようなイメージを持ってもらえればと思います。では、以降では pytest を使用する準備や実行方法、そして具体的な例を使った説明に進んでいきたいと思います。

pytest の使用準備と実行方法

pytest のインストール

pytest 使用するにはパッケージのインストールが必要です。以下のコマンドでインストールしてください。完了すれば pytest の実行環境が整います。

pip install pytest

pytest の実行方法

pytest を実行するには、テスト対象プログラムが配置されているフォルダにて以下コマンドを実行します。なお、test_sample.py の部分はテスト対象のテストプログラム名を指定してください。

pytest -v test_sample.py

なお、通常は複数のテストプログラムをまとめて実行したくなるかと思います。pytest は、test から始まる名前のファイルをテスト対象として判断してくれるため、以下のようにファイル名を省略すれば、該当フォルダ内を探索して test から始まる名前のファイルを順番にテストしてくれます。

pytest -v

また、テストプログラム内で print 等の標準出力をしている場合、上記のオプションだけでは個々のテストプログラムの print は表示されません。print 内容を表示したい場合は、以下のように「-s」オプションをつけて実行してください。

pytest -v -s

他にも pytest のオプションとして指定できるものがありますので、以下コマンドでヘルプを確認してみてもらえるとよいかなと思います。

pytest --help

pytest によるテストの実装例

ここからは、より具体的に pytest を使用したテスト実装例を見ていきます。まずは、以降で説明する関連プログラムをまとめて示します。テスト対象の sample.py、テストプログラムの test_sample.py、テスト用設定の conftest.py があります。詳細内容は後ほど順番に説明していきます。

sample.py:テスト対象プログラム

class Sample:
    """Sampleクラス"""

    def add_and_double(self, x, y):
        """xとyを足して2倍した値を返却する

        Args:
            x: 入力値1
            y: 入力値2
        """
        # intでない場合は、ValueErrorとする
        if not isinstance(x, int) or not isinstance(y, int):
            raise ValueError

        # 計算処理
        result = x + y
        result *= 2

        return result

test_sample.py:テストプログラム

import pytest

import sample


# スキップ用フラグ
SKIP_FLAG = True


class TestSample:
    """Sampleクラスのテスト用クラス"""

    @classmethod
    def setup_class(cls):
        print("\nStart TestSample")
        cls.temp = sample.Sample()

    @classmethod
    def teardown_class(cls):
        print("\nEnd of TestSample")
        del cls.temp

    def setup_method(self, method):
        print(f"\nStart method name: {method.__name__}")

    def teardown_method(self, method):
        print(f"\nEnd method name: {method.__name__}")

    def test_add_and_double(self):
        """テストケース1: 正常計算"""
        assert self.temp.add_and_double(1, 1) == 4
        assert self.temp.add_and_double(2, 2) == 8

    def test_add_and_double_raise(self):
        """テストケース2: 例外処理"""
        with pytest.raises(ValueError):
            self.temp.add_and_double("1", 1)
        with pytest.raises(ValueError):
            self.temp.add_and_double(1, "1")
        with pytest.raises(ValueError):
            self.temp.add_and_double("1", "1")

    @pytest.mark.skip(reason="skip理由:xxxxxxxxxx")
    def test_add_and_double_skip(self):
        """スキップ確認用"""
        assert self.temp.add_and_double(1, 1) == 4

    @pytest.mark.skipif(SKIP_FLAG is True, reason="条件付きskip理由:xxxxxxxxx")
    def test_add_and_double_skipif(self):
        """条件付きスキップ確認用"""
        assert self.temp.add_and_double(1, 1) == 4

    def test_add_and_double_option(self, request):
        """フィクスチャを使ってテストする場合
        ※requestはpytestで定義されているフィクスチャなのでこのように使うものと覚える

        Args:
            request: フィクスチャ
        """
        os_name = request.config.getoption("--os-name")
        if os_name == "windows":
            print("dir")
        elif os_name == "linux" or os_name == "mac":
            print("ls")
        assert self.temp.add_and_double(1, 1) == 4

    def test_add_and_double_original(self, target_numbers):
        """独自フィクスチャを使ってテストする場合

        Args:
            target_numbers: テスト対象数値リストを返す独自フィクスチャ
        """
        print(target_numbers)
        assert self.temp.add_and_double(1, 1) == 4

    def test_add_and_double_original_csv(self, open_csv_file):
        """独自フィクスチャを使ってテストする場合
        csvファイルなどのオープン/クローズをフィクスチャ側で実行

        Args:
            open_csv_file: csvファイルを開く独自フィクスチャ
        """
        print(open_csv_file)
        open_csv_file.write("test1,test2,test3")
        assert self.temp.add_and_double(1, 1) == 4

conftest.py:テスト用の設定

import pytest


def pytest_addoption(parser):
    """テストオプション用の関数"""
    parser.addoption("--os-name", default="windows", help="os name")


@pytest.fixture()
def target_numbers():
    """テスト対象数値リストを返却する

    Returns:
        テスト対象数値リスト
    """
    return [1, 5, 10]


@pytest.fixture()
def open_csv_file():
    """csvファイルをオープンして渡す
    yieldを使用することで終了時にファイルクローズする

    Yields:
        csvファイルオブジェクト
    """
    print("before open")
    with open("test.csv", "w+", encoding="utf-8") as csv_file:
        yield csv_file
    print("\nafter")

以下は、上記全てのフォルダを同一フォルダに配置し、当該フォルダでコマンドを実行した結果です。オプションは「-v」のみの場合と「-v -s」の場合の結果を示します。

実行結果「pytest -v」を実行

> pytest -v
=========================================================== test session starts ===========================================================
platform win32 -- Python 3.13.1, pytest-8.4.2, pluggy-1.6.0 -- D:\PycharmProjects\python-tech-sample-source\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\PycharmProjects\python-tech-sample-source
configfile: pyproject.toml
collected 7 items                                                                                                                          

test_sample.py::TestSample::test_add_and_double PASSED                                                                               [ 14%]
test_sample.py::TestSample::test_add_and_double_raise PASSED                                                                         [ 28%]
test_sample.py::TestSample::test_add_and_double_skip SKIPPED (skip理由:xxxxxxxxxx)                                                   [ 42%]
test_sample.py::TestSample::test_add_and_double_skipif SKIPPED (条件付きskip理由:xxxxxxxxx)                                          [ 57%]
test_sample.py::TestSample::test_add_and_double_option PASSED                                                                        [ 71%]
test_sample.py::TestSample::test_add_and_double_original PASSED                                                                      [ 85%]
test_sample.py::TestSample::test_add_and_double_original_csv PASSED                                                                  [100%]

====================================================== 5 passed, 2 skipped in 0.04s =======================================================

実行結果 「pytest -v -s」を実行

> pytest -v -s
=========================================================== test session starts ===========================================================
platform win32 -- Python 3.13.1, pytest-8.4.2, pluggy-1.6.0 -- D:\PycharmProjects\python-tech-sample-source\venv\Scripts\python.exe
cachedir: .pytest_cache
rootdir: D:\PycharmProjects\python-tech-sample-source
configfile: pyproject.toml
collected 7 items                                                                                                                          

test_sample.py::TestSample::test_add_and_double
Start TestSample

Start method name: test_add_and_double
PASSED
End method name: test_add_and_double

test_sample.py::TestSample::test_add_and_double_raise
Start method name: test_add_and_double_raise
PASSED
End method name: test_add_and_double_raise

test_sample.py::TestSample::test_add_and_double_skip SKIPPED (skip理由:xxxxxxxxxx)
test_sample.py::TestSample::test_add_and_double_skipif SKIPPED (条件付きskip理由:xxxxxxxxx)
test_sample.py::TestSample::test_add_and_double_option
Start method name: test_add_and_double_option
dir
PASSED
End method name: test_add_and_double_option

test_sample.py::TestSample::test_add_and_double_original
Start method name: test_add_and_double_original
[1, 5, 10]
PASSED
End method name: test_add_and_double_original

test_sample.py::TestSample::test_add_and_double_original_csv
Start method name: test_add_and_double_original_csv
before open
<_io.TextIOWrapper name='test.csv' mode='w+' encoding='utf-8'>
PASSED
after

End method name: test_add_and_double_original_csv

End of TestSample


====================================================== 5 passed, 2 skipped in 0.04s =======================================================

以降では上記プログラムを使ってポイントとなるテスト記載方法を説明していきます。

テストの基本要素

テストの基本構成についてまず説明します。以下は test_sample.py 内の TestSample クラスの一部抜粋です。

class TestSample:
    """Sampleクラスのテスト用クラス"""

    def test_add_and_double(self):
        """テストケース1: 正常計算"""
        assert self.temp.add_and_double(1, 1) == 4
        assert self.temp.add_and_double(2, 2) == 8

TestSample というクラスを作成し、その中にテスト用メソッドをどんどん記載していきます。test_add_and_double(self) は、正常計算結果を確認することを意図して作成したテストメソッドです。

テスト結果の判定を行う場合は assert を使って判定条件を記載します。

Python 標準のテストフレームワークの unittest では、TestCase クラスを継承して self.assertEqual のようなメソッドで判定するため、判定メソッドを覚えたり調べたりといった点が面倒な点として挙げられます。一方で、pytest では判定は Python の比較演算を使用できるので直感的にテストを実装できるのがメリットです。

上記で記載しているケースは問題なく処理がされているため、実行結果を見ると以下のように PASSED となります。

test_sample.py::TestSample::test_add_and_double PASSED

では、失敗する状況を考えてみます。例えば「assert self.temp.add_and_double(2, 2) == 4」のようなテストをした場合には以下のように失敗となります。(2 + 2) × 2 = 8ですのでテストケースが間違っている例です。

================================================= FAILURES ================================================== 
______________________________________ TestSample.test_add_and_double _______________________________________ 

self = <test_sample.TestSample object at 0x000002BEA713E0B0>

    def test_add_and_double(self):
        """テストケース1: 正常計算"""
        assert self.temp.add_and_double(1, 1) == 4
>       assert self.temp.add_and_double(2, 2) == 4
E       assert 8 == 4
E        +  where 8 = <bound method Sample.add_and_double of <sample.Sample object at 0x000002BEA713EDD0>>(2, 
2)
E        +    where <bound method Sample.add_and_double of <sample.Sample object at 0x000002BEA713EDD0>> = <sample.Sample object at 0x000002BEA713EDD0>.add_and_double
E        +      where <sample.Sample object at 0x000002BEA713EDD0> = <test_sample.TestSample object at 0x000002BEA713E0B0>.temp

test_sample.py:38: AssertionError

このように想定と出力結果が異なる場合には FAILURE として失敗が表示されます。

なお、テストの失敗は「テスト対象プログラムの処理結果が誤っている場合」や上記のように「テストケース自体が誤っているような場合」等、色々ありますのでエラーを見つつ、プログラムを修正していくようにしてください。

例外処理

次に、例外処理をテストする場合のテストメソッドの記載方法です。

    def test_add_and_double_raise(self):
        """テストケース2: 例外処理"""
        with pytest.raises(ValueError):
            self.temp.add_and_double("1", 1)
        with pytest.raises(ValueError):
            self.temp.add_and_double(1, "1")
        with pytest.raises(ValueError):
            self.temp.add_and_double("1", "1")

今回のテスト対象プログラム sample.pyadd_and_double メソッドでは、int ではない引数が渡された場合に ValueError を返却することになっています。

このような場合には、上記のように pytest.raises を使用した with 句を用いて確認します。もし「self.temp.add_and_double(1, 1)」のように例外をあげないような処理を with 句内に記載するとテストは失敗となります。

setupteardown

次に、各テストの実行前後にテストのセットアップや完了時処理をするための setupteardown についての記載方法です。

    @classmethod
    def setup_class(cls):
        print("\nStart TestSample")
        cls.temp = sample.Sample()

    @classmethod
    def teardown_class(cls):
        print("\nEnd of TestSample")
        del cls.temp

    def setup_method(self, method):
        print(f"\nStart method name: {method.__name__}")

    def teardown_method(self, method):
        print(f"\nEnd method name: {method.__name__}")

setup は、テストの前に準備をするために用意されているもので setup_classsetup_method があります。その名の通りクラス生成時のセットアップが setup_class で、メソッドの実行時のセットアップが setup_method です。

一方で、teardown は、テストの後に処理を実行するために用意されているもので、teardown_classteardown_method があります。それぞれクラスとメソッドに対応します。

上記例では、テスト開始と終了、各メソッドの開始と終了が分かるように print しています。print は、pytest の実行時に -s オプションをつけた場合に表示できますが、実行結果を見ると以下のように表示されます。

> pytest -v -s

..(省略)...

test_sample.py::TestSample::test_add_and_double
Start TestSample

Start method name: test_add_and_double
PASSED
End method name: test_add_and_double

test_sample.py::TestSample::test_add_and_double_raise
Start method name: test_add_and_double_raise
PASSED
End method name: test_add_and_double_raise

...(省略)...

End of TestSample

setup_classteardown_classprint は最初と最後のみ表示されていることが分かります。一方で setup_methodteardown_methodprint は各メソッドの実行前後で表示されます。

また、setup_class ではあらかじめテスト対象のクラス Sample をオブジェクト化しており、teadown_class では (特に必須なわけではないですが) オブジェクトを del しています。このようにすることで、各テストメソッドでは毎回クラスをオブジェクト化する必要がなくなりますし、テスト終了時の処理を必要に応じて記載できます。

テスト前後のタイミングで何か処理を記載したい場合には setupteardown をうまく活用しましょう。

テストのスキップ

テストを多く記載していると一部関数やメソッドをスキップして処理を実行したくなる場合があります。テストをスキップする場合の記載方法について見ていきましょう。

通常のスキップ

一部のテストメソッドをスキップしたい場合には、以下のように @pytest.mark.skip デコレータを使用します。reason に スキップ理由などを記載しておき、実行時に表示することが可能です。

    @pytest.mark.skip(reason="skip理由:xxxxxxxxxx")
    def test_add_and_double_skip(self):
        """スキップ確認用"""
        assert self.temp.add_and_double(1, 1) == 4

スキップされると以下のような実行結果となります。

test_sample.py::TestSample::test_add_and_double_skip SKIPPED (skip理由:xxxxxxxxxx) 
条件付きスキップ

条件に一致する場合にテストをスキップしたいときもあるかと思いますが、その場合は以下のように @pytest.mark.skipif デコレータを使用して条件を引数に渡します。スキップ理由は reason 引数に渡すことで表示することが可能です。

# スキップ用フラグ
SKIP_FLAG = True

...(省略)

    @pytest.mark.skipif(SKIP_FLAG is True, reason="条件付きskip理由:xxxxxxxxx")
    def test_add_and_double_skipif(self):
        """条件付きスキップ確認用"""
        assert self.temp.add_and_double(1, 1) == 4

スキップされると以下のような実行結果となります。

test_sample.py::TestSample::test_add_and_double_skipif SKIPPED (条件付きskip理由:xxxxxxxxx)

フィクスチャ(fixture)を使ったテスト

テストのフィクスチャ (fixture) とは、テストに必要な前提の状態や条件の集合の事を言います。テストコンテキストとも呼ばれます。

pytest では、pytest で提供されているフィクスチャを使用したり、自分で独自フィクスチャを作成して使用したりすることができるようになっています。pytest の「Fixtures reference」にフィクスチャに関するリファレンスページがあります。ページを見てもらうと分かりますが様々なビルトインのフィクスチャがあります。

pytest では conftest.py という設定用のファイルを用意して使うことでフィクスチャをうまく扱っていくことができます。

以降では、pytest で提供されているフィクスチャの使用例の 1 例として「request フィクスチャを使ってコマンドライン引数を扱う方法」と「独自のフィクスチャ作成方法」について紹介します。

request フィクスチャを使ってコマンドライン引数を扱う方法

pytest で提供されている request フィクスチャを使って、pytest のコマンドライン引数を扱う方法を紹介します。まず、コマンドライン引数を使えるようにするには、以下のように conftest.py に記載します。

テスト用設定プログラム:conftest.py(対象箇所のみ抜粋)

"""pytestに関する各種設定を定義する"""
import pytest


def pytest_addoption(parser):
    """テストオプション用の関数"""
    parser.addoption("--os-name", default="windows", help="os name")

上記のように pytest_addoption(parser) というメソッドを実装し、parser.addoption にオプションを定義することで pytest のコマンドライン引数として使用できるようになります。

上記の例では「--os-name」という引数を定義しています。また、引数省略時の設定として default="windows" と設定しています。help では「pytest --help」としてヘルプを表示した時の説明文を指定できます。実際にヘルプを表示してみると以下のようにCustom options として表示されます。

> pytest --help
usage: pytest [options] [file_or_dir] [file_or_dir] [...]

...(省略)...

Custom options:
  --os-name=OS_NAME     os name

...(省略)...

では、実際にこのコマンドライン引数の入力をテスト側で使用するための記載方法を見ていきましょう。

test_sample.py:テストプログラム(対象箇所のみ抜粋)

    def test_add_and_double_option(self, request):
        """フィクスチャを使ってテストする場合
        ※requestはpytestで定義されているフィクスチャなのでこのように使うものと覚える

        Args:
            request: フィクスチャ
        """
        os_name = request.config.getoption("--os-name")
        if os_name == "windows":
            print("dir")
        elif os_name == "linux" or os_name == "mac":
            print("ls")
        assert self.temp.add_and_double(1, 1) == 4

テスト側でフィクスチャを使用する場合は、上記のようにメソッドの引数として受け取ります。requestpytest で定義されているものなので、このように指定するものだと覚えてしまっていいかと思います。

先ほど追加したコマンドライン引数は「request.config.getoption("--os-name")」というようにすることで取得することができます。このようにして取得したコマンドライン引数の指定値をベースにテストの挙動を変えることができます。

例えば --os-name=linuxmac でも構いません)と指定して処理を実行するとテスト結果は以下のようになります。

> pytest -v -s --os-name=linux
...(省略)...

test_sample.py::TestSample::test_add_and_double_option
Start method name: test_add_and_double_option
ls
PASSED
End method name: test_add_and_double_option

...(省略)...

linux もしくは mac と指定した場合は「ls」と表示するようにテストでは実装しているので、そのように表示されていることが分かります。--os-name を省略した場合は、default"windows" と定義したので「dir」と表示されます。

このように conftest.pyrequest フィクスチャをつかうことでコマンドライン引数を使ってテストを制御することが可能になります。

なお、pytest のフィクスチャは他にも色々あるため Fixtures reference を参考に色々調べてみてもらえるとよいかと思います。

独自フィクスチャの作成

pytest では、上記で紹介した request のように pytest が提供しているフィクスチャだけではなく、独自フィクスチャを作成して使用することが可能となっています。

独自フィクスチャを作成する場合には、conftest.py 内に @pytest.fixture() のデコレータをつけた関数を定義することで実現できます。いくつか例をみてみましょう。

【例:数値リストの返却】

1 つ目の例として、テスト対象の数値リストを返すようなフィクスチャを作成する例を以下で見てみましょう。まずは、conftest.py にフィクスチャの関数を定義します。

テスト用設定プログラム:conftest.py(対象箇所のみ抜粋)

"""pytestに関する各種設定を定義する"""
import pytest


@pytest.fixture()
def target_numbers():
    """テスト対象数値リストを返却する

    Returns:
        テスト対象数値リスト
    """
    return [1, 5, 10]

@pytest.fixture() デコレータをつけて target_numbers という数値リストを返すだけの関数を定義しています。

実際にこのフィクスチャをテスト側で使用するための記載方法を見ていきましょう。

テストプログラム:test_sample.py(対象箇所のみ抜粋)

    def test_add_and_double_original(self, target_numbers):
        """独自フィクスチャを使ってテストする場合

        Args:
            target_numbers: テスト対象数値リストを返す独自フィクスチャ
        """
        print(target_numbers)
        assert self.temp.add_and_double(1, 1) == 4

テストを実行する側では上記で紹介した request の例と同様にテスト関数で作成したフィクスチャ関数名を「def test_add_and_double_original(self, target_numbers):」のように指定します。

実際の実行結果は以下のようになります。

test_sample.py::TestSample::test_add_and_double_original
Start method name: test_add_and_double_original
[1, 5, 10]
PASSED
End method name: test_add_and_double_original

target_numbersprint した結果を見てみると [1, 5, 10] という関数の戻り値が表示されていることが分かります。このようにテストで使用する数値リスト等を返却するといったことが独自フィクスチャだとできるようになります。

今回は数値リストを返すような簡単な例でフィクスチャを定義しましたが、どのような定義も可能です。このように独自フィクスチャでテスト条件となる値等を定義しておくと複数のテストメソッドで使用できるようになり、テスト条件とテスト実装をうまく分離することができるようになります。

【例:ファイルオープン/クローズをフィクスチャ側で実行】

独自フィクスチャの作り方として、もう 1 つ面白い使い方をご紹介します。テストで使用する csv ファイルをオープンして渡すような以下のような独自フィクスチャを作ることを考えてみます。

テスト用設定プログラム:conftest.py(対象箇所のみ抜粋)

@pytest.fixture()
def open_csv_file():
    """csvファイルをオープンして渡す
    yieldで返すことで終了時にファイルクローズする

    Yields:
        csvファイルオブジェクト
    """
    print("before open")
    with open("test.csv", "w+", encoding="utf-8") as csv_file:
        yield csv_file
    print("\nafter")

上記は test.csv ファイルをオープンしてオブジェクトを返却する関数ですが、ポイントは、with 句を使って yield でオブジェクトを返している点です。このようにすると、テスト側でファイルの使用が終わった際に with 句を抜けるのでファイルが自動的にクローズされます。

実際にこのフィクスチャをテスト側で使用するための記載方法を見ていきましょう。

テストプログラム:test_sample.py(対象箇所のみ抜粋)

    def test_add_and_double_original_csv(self, open_csv_file):
        """独自フィクスチャを使ってテストする場合
        csvファイルなどのオープン/クローズをフィクスチャ側で実行

        Args:
            open_csv_file: csvファイルを開く独自フィクスチャ
        """
        print(open_csv_file)
        open_csv_file.write("test1,test2,test3")
        assert self.temp.add_and_double(1, 1) == 4

使い方は、これまで紹介してきたフィクスチャと同じです。わたってきたオブジェクトを使って write で書き込みを行っています。

実際の実行結果は以下のようになります。

Start method name: test_add_and_double_original_csv
before open
<_io.TextIOWrapper name='test.csv' mode='w+' encoding='utf-8'>
PASSED
after

今回 with 句を抜けたことが分かりやすいように "after" という文字列を表示しています。このようにフィクスチャ側でファイルのオープン / クローズを実行可能です。

まとめ

Python プログラムのテストを実行するためのフレームワークである pytest モジュールについて解説しました。pytest は、Python 標準テストフレームワークの unittest モジュールの機能制限などに不満を持つ開発者によって開発されたテストフレームワークの 1 つです。

この記事内では pytest の実行方法やテスト実装例について紹介してきました。setupteadown を使ったテスト準備やテストのスキップ、フィクスチャをつかったテストについて紹介しています。

pytest は、Python のテストフレームワークとして非常に有用なパッケージです。皆さんも色々と使い方を調べてもらうと面白いと思います。

また、テスト駆動開発 (TDD:Test-Driven Development) という自動テストを中心にした高品質のソフトウェア開発をするための方法論は Python コミュニティでは幅広く利用されています。pytest はテスト駆動開発においても有用なテストフレームワークです。テスト駆動開発については「エキスパートPythonプログラミング」という書籍にも記載がありますので、興味があれば参考にしてください。

pytest の公式サイトはこちらを参照してください。

ソースコード

上記で紹介しているソースコードについては GitHub にて公開しています。参考にしていただければと思います。

あわせて読みたい
【Python Tech】プログラミングガイド
【Python Tech】プログラミングガイド
ABOUT ME
ホッシー
ホッシー
システムエンジニア
はじめまして。当サイトをご覧いただきありがとうございます。 私は製造業のメーカーで、DX推進や業務システムの設計・開発・導入を担当しているシステムエンジニアです。これまでに転職も経験しており、以前は大手電機メーカーでシステム開発に携わっていました。

プログラミング言語はこれまでC、C++、JAVA等を扱ってきましたが、最近では特に機械学習等の分析でも注目されているPythonについてとても興味をもって取り組んでいます。これまでの経験をもとに、Pythonに興味を持つ方のお役に立てるような情報を発信していきたいと思います。どうぞよろしくお願いいたします。

※キャラクターデザイン:ゼイルン様
記事URLをコピーしました