#python #django #pytest #django-tests #pytest-django
#python #django #pytest #django-тесты #pytest-django
Вопрос:
Как я могу использовать pytest приспособление в TestCase
методе? Несколько ответов на похожие вопросы, похоже, подразумевают, что мой пример должен работать:
import pytest
from django.test import TestCase
from myapp.models import Category
pytestmark = pytest.mark.django_db
@pytest.fixture
def category():
return Category.objects.create()
class MyappTests(TestCase):
def test1(self, category):
assert isinstance(category, Category)
Но это всегда приводит к ошибке:
TypeError: test1() missing 1 required positional argument: 'category'
Я понимаю, что мог бы просто преобразовать этот тривиальный пример в функцию, и это сработало бы. Я бы предпочел использовать django TestCase
, потому что он включает поддержку импорта традиционных файлов «django fixture», которые требуются для нескольких моих тестов. Преобразование моих тестов в функции потребует повторной реализации этой логики, поскольку не существует документированного способа импорта «django fixtures» с помощью pytest (или pytest-django).
версии пакетов:
Django==3.1.2
pytest==6.1.1
pytest-django==4.1.0
Ответ №1:
Мне проще использовать подход «usefixtures». Он не показывает волшебный 2-й аргумент функции и явно помечает класс для наличия приспособлений.
@pytest.mark.usefixtures("category")
class CategoryTest(TestCase):
def test1(self):
assert Category.objects.count() == 1
Комментарии:
1. Спасибо, но в моем случае это не сработало бы, потому что «pytest fixtures» не следует применять ко всем тестам в классе. Кроме того, мне нужно получить доступ либо к модели, возвращаемой из приспособления, либо к ее первичному ключу. При этом я нашел обходной путь, показанный в ответе, который я опубликовал.
2. Да, я подумал, что их не должно быть, но это функционально идентично тому, что вы пытались сделать выше. Я предпочитаю не смешивать pytest и TestCase, а также выбирать лучший инструмент для текущей работы.
Ответ №2:
Я решил переписать логику django fixture, используя «pytest fixture», который применяется в области session
видимости. Все, что вам нужно, это одно приспособление в conftest.py
файле в корне вашего тестового каталога:
import pytest
from django.core.management import call_command
@pytest.fixture(scope='session')
def django_db_setup(django_db_setup, django_db_blocker):
fixtures = [
'myapp/channel',
'myapp/country',
...
]
with django_db_blocker.unblock():
call_command('loaddata', *fixtures)
Это позволило мне полностью отказаться от тестов на основе классов и просто использовать тесты на основе функций.
Ответ №3:
Зачем вам нужен TestCase? Я обычно использую класс Python и создаю там тесты.
Пример
import pytest
from django.urls import reverse
from rest_framework import status
from store.models import Book
from store.serializers import BooksSerializer
@pytest.fixture
def test_data():
"""Поднимает временные данные."""
Book.objects.create(name='Book1', price=4000)
@pytest.fixture
def api_client():
"""Возвращает APIClient для создания запросов."""
from rest_framework.test import APIClient
return APIClient()
@pytest.mark.django_db
class TestBooks:
@pytest.mark.usefixtures("test_data")
def test_get_books_list(self, api_client):
"""GET запрос к списку книг."""
url = reverse('book-list')
excepted_data = BooksSerializer(Book.objects.all(), many=True).data
response = api_client.get(url)
assert response.status_code == status.HTTP_200_OK
assert response.data == excepted_data
assert response.data[0]['name'] == Book.objects.first().name