概要
- pytest においてテストの前処理・後処理を記述する方法をまとめた
fixture を使用する
- @pytest.fixture() を付与した関数内の処理を呼び出すことができる
- 以下の例では、test_sample() に hoge() を渡すことで、test_sample() の前に hoge() が呼び出される。
import pytest
@pytest.fixture()
def hoge():
print("setup")
message = "hoge"
return message
class TestApp:
def test_sample(self, hoge):
print(hoge)
事前処理として "setup" が出力されている
# command
pytest test.py -s
# 出力
test.py setup
hoge
.
事前処理だけでなく、事後処理を定義することもできる
その場合は、以下のように戻り値を yield で返せばよい
(request-context オブジェクトであれば 「addfinalizer に事後処理となるメソッドを渡す」という方法がより安全であるそうだが、ここでは割愛する)
import pytest
@pytest.fixture()
def hoge():
print("setup")
message = "hoge"
yield message
print("teardown")
class TestApp:
def test_sample(self, hoge):
print(hoge)
テスト関数が終了した後に、hoge() で定義した事後処理が実行されている
# command
pytest test.py -s
# 出力
test.py setup
hoge
.teardown
関数単位ではなく、クラス単位やモジュール単位で事前処理を行いたい場合は scope を設定するとよい
import pytest
@pytest.fixture(scope='class')
def hoge():
print("setup")
message = "hoge"
yield message
print("teardown")
class TestApp:
def test_sample(self):
print(hoge)
def test_sample2(self):
print(hoge)
各テスト関数毎ではなく、クラス単位で fixture が呼び出されている
# command
pytest test.py -s
# 出力結果
test.py setup
hoge
.hoge
.teardown
scope について
scope を定義することで fixture が呼び出されるタイミングと、事後処理が呼び出されるタイミングを定義できる
以下の 5 つのいずれかを定義できる (デフォルトは function)
- function
- class
- module
- package
- session
指定した単位で fixture で定義された事前処理と事後処理が呼び出される
session を扱う際の注意点
- テストモジュール内で fixture を定義した上で複数のモジュールを実行すると、1度のテスト実行でモジュールの数だけ fixture が呼び出されてしまう。
- 以下の構成で test_app.py に fixture を定義し、tests/ 以下のテストを実行すると、fixture が 2 回呼び出されてしまう
root
├─ src
│ └─ app.py
└─ tests
├─ test_app.py
└─ test_app2.py
- その場合は後述の confest.py に fixture を定義すると、scope が正しく機能する
root
├─ src
│ └─ app.py
└─ tests
├─ conftest.py
├─ test_app.py
└─ test_app2.py
confest.py について
- fixture を conftest.py で定義することで、同じディレクトリにある複数のテストモジュールで fixture が使用できるようになる
- また、上位のディレクトリにある conftest 内で定義された fixture は使用できるが、下位のものは使用できない。
以下の例であれば、test_app3.py からは tests/conftest.py を使用できる。
一方、test_app.py からは test_dir2/conftest.py は使用できない。
ディレクトリ構成
root
└─ tests
├─ conftest.py
├─ test_app.py
└─ test_dir2
├─ conftest.py
└─ test_app2.py
サンプルコード
# tests/conftest.py
import pytest
@pytest.fixture(scope="function")
def hoge():
print("start")
message = "ほげ"
yield message
print("done")
# tests/conftest.py
class TestApp:
def test_sample(self, hoge):
print(hoge)
def test_sample2(self, hoge):
print(hoge)
class TestApp1_2:
def test_sample(self, hoge):
print(hoge)
import pytest
@pytest.fixture(scope="function")
def hoge2():
# setup
print("start2")
message = "ほげ2"
yield message
print("done2")
class TestApp2:
# 上位ディレクトリの conftest.py に定義された fixture は使用可能
def test_sample(self, hoge):
print(hoge)
def test_sample2(self, hoge2):
print(hoge2)
以下の実行結果から、test_app2.py で上位にある fixture を呼び出せている
# command in root/tests/
pytest -s
# 出力結果
test_app.py start
ほげ
.done
start
ほげ
.done
start
ほげ
.done
test_dir2\test_app2.py start
ほげ
.done
start2
ほげ2
.done2
まとめ
- 上記の fixture と conftest.py を適切に使用できれば、テストコードをより簡潔に記述できる