pytestの使い方、Pythonプログラムのテストを記述する2

前回に引き続き、pytestの要素技術を勉強していきます。

全てのチュートリアルは長いので、flaskチュートリアルで使われているものをピックアップするのが良さそう・・・

flaskのチュートリアルで出てきたpytest、とても世界が広いので、とりあえずテストができるような要素である「fixture」と「confest.py」というものが何者かを調べました。前回のpytestに関する記事の続きとなります。

ぱんだクリップ
pytestの使い方、Pythonプログラムのテストを記述する1 | ぱんだクリップ flaskチュートリアルで、テストする項目にきましたが、pytestとcoverageという仕組みを利用していてよくわかりませんでした。 まずはpytestについてどんな風に使うかみてみ...

こんな人の役に立つかも

・pytestがどんなものか知りたい人

・Pythonのテストツールpytestを使いたい人

・flaskのテストをしたく、pytestを理解したい人

目次

Fixtureとは??

pytestにはfixtureという仕組みがあり、「@pytest.fixture」として定義することで、「テストで何回も共有するようなプログラムブロックを作成」することができます。

公式のドキュメントには、次のような項目があり、サンプルプログラムが掲載されていました。

あわせて読みたい

英語でfixtureは備品という意味みたいです。プログラムを取って使えるようにするというような感じでしょうか・・・

fixtureのサンプルプログラムで検証

「test_sample.py」として、次のプログラムを作成しました。

import pytest

#①fixtureの定義
@pytest.fixture
def smtp_connection():
    import smtplib
    return smtplib.SMTP("smtp.gmail.com", 587, timeout=5)

#②fixtureを関数の引数として渡す
def test_ehlo(smtp_connection):
    response, msg = smtp_connection.ehlo()
    assert response == 250
    #必ずエラーが出るようにassert 0と入れています。これをとると正常にテストが終了します。
    assert 0  # for demo purposes

①のfixtureの定義では、「@pytest.fixture」とすることで「smtp_connection」というfixtureを作成しています。fixtureの内容としては、smtplibでメール送信のオブジェクトを作成するというような内容となっています。(ポート番号587でsmtp.gmail.comに接続)

メールの送信には、「SMTPサーバー」と「ポート番号」を設定する必要があります。smtplibを利用してメール送信を行うとき、smtplibのSMTPに対して「SMTPサーバー」と「ポート番号」(+タイムアウト時間)を設定する処理が必ず必要になってきます。

今回のサンプルの場合、「メール送信を行う」ための前処理に当たる部分が「fixture」として定義されていることがわかります。そして、fixtureは「送信サーバー、ポート番号」を入れたSMTPを返すようなものになっています。

②では、fixtureに設定した「smtp_connection」を引数にとることで、smtp_connectionをsmtplibのオブジェクトのように扱っています。「smtp_connection.ehlo」のようにメソッドを呼び出すことができるようです。ehloは、SMTPサーバーに対して身元を送信するようなメソッドです。

SMTPの仕組みがわかりやすいページ(興味がある場合は^^;)

Customers Mail Cloud ブログ
SMTPによるメール送信のしくみ - Customers Mail Cloud ブログ メールを送信するために使用するプロトコル(SMTP)について説明します。 SMTPはRFC 821で定義され、何回か改定して現在はRFC 5321になっています。 改定により細かなとこ...

サンプルプログラムの実行

pytestフォルダにテストプログラムを作成していますので、階層に移動します。

cd pytest

前回構築したvenv仮想環境を立ち上げます。(windowsの場合は「venv¥Script¥activate」)

$. venv/bin/activate

pytestコマンドでテストを実行します。

(venv)$ pytest

無事、テストが行われ、エラーが出ました 笑

サンプルプログラムでは、fixtureとして定義することでいろんなところで必要にされそうな「SMTPサーバーに接続する」というメール送信の前処理を共有することができるようになりました。

これは、Webアプリのテストだとデータベースへの接続など、そういったテストに利用できそうです。

conftest.py

Fixtureを特定のPythonファイルに記述するのではなく、「conftest.py」に記載することで、fixtureを共有することができます。

あわせて読みたい

conftest.pyの検証

先ほど検証したtest_sample.pyを次のよう「conftest.py」と「test_sample.py」に分割してみます。

conftest.py

「conftest.py」としてfixtureのプログラムを作成します。(プログラムの上の部分です)

import pytest

@pytest.fixture
def smtp_connection():
    import smtplib

    return smtplib.SMTP("smtp.gmail.com", 587, timeout=5)

test_sample.py

test_sample.pyは、次のようになります。ちなみに、今回はテストが成功するように「assert 0」をコメントアウトしてみました。

def test_ehlo(smtp_connection):
    response, msg = smtp_connection.ehlo()
    assert response == 250
    #assert 0  # for demo purposes

それでは、pytestコマンドでテストしてみます。

(venv)$ pytest

無事テストが行われ、ファイルの分割でもできていることがわかります。

flaskで利用しているpytestの機能は主にfixtureとconftestへの分割がわかれば良さそうな感じです。

テストを切り離した構成

最後に、テスト用のファイルを分割するような構成なのですが、公式ドキュメントのような構成にすることで、本プログラムとテストプログラムが分割できて良いそうです。

「tests」というフォルダをプロジェクトフォルダと同じ階層に設置して、プロジェクトはモジュールとして読み込むようにします。

flaskのプロジェクトフォルダ構成はこの構成を取っていますね。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次