Pythonのテストでpytestを使ってます

最近Pythonでプログラミングをしています。仕事でPythonを使うのは初めてですが、書きやすくてけっこう捗ってます。Pythonではユニットテストは組み込みのunittestを利用するのがおそらくデファクトスタンダードだと思うんですが、今はpytest使ってます。個人的備忘録です。

pytestを使い始めた理由

最近、自分で設計をするプログラムに関してはどの言語でもDotEnvを利用して作るようにしています。それでテスト実行する時は環境変数を切り替えて実行したいのですが、unittestだとpytestのpytest-envのような仕組みが探した限り見つかりませんでした。それにpytestであればconftest.pyでテスト前にフックを入れられたり、仕組み的に充実しているように思いました。unittestでももっと調べればあるかもですが、今回はひとまずpytestにしてます。

pytestのセットアップ

pytestとpytest-envをインストールします。pytest-envは環境変数の書き換えをしない場合は不要です。

$ pip install pytest pytest-env

pytest.iniを作成します。

[pytest]
testpaths = tests
env =
    ENV1=env1-for-test

上記はテスト用のpathをtestsフォルダにしています。envで環境変数の書き換えをしています。

conftest.pyを記述する

上記の例で言うと、testsフォルダ中にconftest.pyを保存しておくとそのディレクトリのテスト実行前に読み込まれ実行されます。ぼくの場合は例えばこのconftest.pyの読み込み部分でDBを初期化したりしています。下記は例です。

import os
import sys
from os.path import join, dirname
from dotenv import load_dotenv

dotenv_path = join(dirname(__file__), '../.env')
load_dotenv(dotenv_path)
sys.path.append(join(dirname(__file__), '../'))

if os.environ.get('MYSQL_HOST') == 'localhost':
    with open(os.path.dirname(__file__) + '/../resources/mysql/ddl/ddl.sql', 'r') as stream:
        statement = stream.read()
        initialize_db(statement)

なお、このconftest.pyにテスト毎に起動するsetupやteardownを書く事もできます。ぼくの場合はテストによってSqlAlchemyのListenerをセットアップしたかったので、conftest.pyで設定したりしています。

def pytest_runtest_setup():
    registerer.up()


def pytest_runtest_teardown():
    registerer.down()

テストの実行

基本はpytestと打つだけです。いろいろオプションもあるみたいですが僕の場合は時間がかかるテストは別でフォルダを分けて、普段はignoreオプションつけてテストしてます。

$ pytest
$ pytest --ignore=tests/initegration

まだ使い始めたばかりですが、もっと使い込んでいきたいです。

参考情報