【django】pytest fixtureの使い方
Django/DjangoRESTframeworkについて記事まとめ
fixture | テストで使用するリソースの定義
fixture
は、django
のモデルにアクセスしたり、モックを作成したり出来る機能です。
https://docs.pytest.org/en/6.2.x/fixture.html
@pytest.fixture
として関数を作成することで、その返り値を利用できるようになります。
import pytest
@pytest.fixture
def fixture_1():
print('run-fixture-1')
return 1
def test_example1(fixture_1):
num = fixture_1
assert num == 1
fixtureの値を使い回す範囲設定(scope)
fixture
は、標準では使用するテスト関数毎に呼び出され利用できます。
@pytest.fixture
def fixture_1():
print('run-fixture-1')
return 1
def test_example1(fixture_1):
print("example1")
num = fixture_1
assert num == 1
def test_example2(fixture_1):
print("example2")
num = fixture_1
assert num == 1
pytest -rP
を実行すると
===================================== PASSES =====================================
_________________________________ test_example1 __________________________________
----------------------------- Captured stdout setup ------------------------------
run-fixture-1
------------------------------ Captured stdout call ------------------------------
example1
_________________________________ test_example2 __________________________________
----------------------------- Captured stdout setup ------------------------------
run-fixture-1
------------------------------ Captured stdout call ------------------------------
example2
=============================== 2 passed in 0.05s ================================
毎回呼び出されていることが確認できました。しかし、実行にコストがかかり値を共有したい場合には、scope=""
と指定できます。
例えば、@pytest.fixture(scope="session")
とすることで、再利用される形に変更できます。
===================================== PASSES =====================================
_________________________________ test_example1 __________________________________
----------------------------- Captured stdout setup ------------------------------
run-fixture-1
------------------------------ Captured stdout call ------------------------------
example1
_________________________________ test_example2 __________________________________
------------------------------ Captured stdout call ------------------------------
example2
=============================== 2 passed in 0.05s ================================
他にもscope
の種類としては
function
(デフォルト値)class
module
package
session
があります。
django_db | データベースアクセスを明示
https://pytest-django.readthedocs.io/en/latest/helpers.html
データベースへのアクセスが必要なテストの場合、@pytest.mark.django_db
を使用します。
下記では、django
標準のユーザーモデルを作成し、ユーザー数のチェックを行いました。
import pytest
from django.contrib.auth.models import User
@pytest.mark.django_db
def test_user_create():
User.objects.create_user('test', 'test@test.com', 'test')
assert User.objects.count() == 1
@pytest.mark.django_db
def test_user_create1():
count = User.objects.all().count
assert count == 0
fixture
からUser
モデルを作成し、テストで使用することも可能です。
import pytest
from django.contrib.auth.models import User
@pytest.fixture
def user_1(db):
user = User.objects.create_user('test-user')
print('create-user')
return user
@pytest.mark.django_db
def test_set_check_password(user_1):
user_1.set_password('new-password')
assert user_1.check_password("new-password") is True
@pytest.mark.django_db
def test_set_check_password1(user_1):
assert user_1.username == 'test-user'
create_user
で新しいユーザーを作成しました。
テストでは
set_password
、check_password
でパスワードの検証username
が正しいかどうかの検証
を行いました。
fixtureを共有する(conftest.py)
conftest.py
で作成したfixture
は、ファイル間で共有できます。
Factory & fixture
fixture
の結果が、1回のテストで複数回必要となる状況の場合には、動的にデータを生成する関数(Factory)を定義すると便利です。
データを直接返す代わりにデータを生成する関数を作成します。
import pytest
from django.contrib.auth.models import User
@pytest.fixture
def new_user_factory(db):
def create_app_user(
username: str,
password: str = None,
first_name: str = "firstname",
last_name: str = "lastname",
email: str = "test@test.com",
is_staff: str = False,
is_superuser: str = False,
is_active: str = True
):
user = User.objects.create_user(
username=username,
password=password,
first_name=first_name,
last_name=last_name,
email=email,
is_staff=is_staff,
is_superuser=is_superuser,
is_active=is_active,
)
return user
return create_app_user
@pytest.fixture
def new_user1(db, new_user_factory):
return new_user_factory("Test_user","password","MyName")
@pytest.fixture
def new_user2(db, new_user_factory):
return new_user_factory("Test_user","password", "MyName", is_staff="True")
new_user_factory(db)
で新しくユーザーを作成するファクトリーを作成しました。
また、new_user1(db, new_user_factory)
と他のfixture
との連携も可能です。
import pytest
def test_new_user(new_user2):
print(new_user2.is_staff)
assert new_user2.is_staff
参考
- pytest fixtures: explicit, modular, scalable
- Pytest | Django | Introducing Fixtures and Fixture Factory
- pytest ヘビー🐍ユーザーへの第一歩
- pytest:フィクスチャ(fixture)の使い方
Django/DjangoRESTframeworkについて記事まとめ
コメント