前回に引き続き、pytestの要素技術を勉強していきます。
全てのチュートリアルは長いので、flaskチュートリアルで使われているものをピックアップするのが良さそう・・・
flaskのチュートリアルで出てきたpytest、とても世界が広いので、とりあえずテストができるような要素である「fixture」と「confest.py」というものが何者かを調べました。前回の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の仕組みがわかりやすいページ(興味がある場合は^^;)
サンプルプログラムの実行
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のプロジェクトフォルダ構成はこの構成を取っていますね。