0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【pytest】前処理・後処理を定義する方法

Posted at

概要

  • pytest においてテストの前処理・後処理を記述する方法をまとめた

fixture を使用する

  • @pytest.fixture() を付与した関数内の処理を呼び出すことができる
  • 以下の例では、test_sample() に hoge() を渡すことで、test_sample() の前に hoge() が呼び出される。
test.py
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)

  1. function
  2. class
  3. module
  4. package
  5. 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
# tests/conftest.py
import pytest

@pytest.fixture(scope="function")
def hoge():
    print("start")
    message = "ほげ"

    yield message

    print("done")
tests/test_app.py
# 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)
test_dir2/conftest.py
import pytest

@pytest.fixture(scope="function")
def hoge2():
    # setup
    print("start2")
    message = "ほげ2"

    yield message

    print("done2")
test_dir2/test_app2.py
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 を適切に使用できれば、テストコードをより簡潔に記述できる
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?