¿Cómo puedo usar un accesorio pytest dentro de un método TestCase ? Varias respuestas a preguntas similares parecen implicar que mi ejemplo debería funcionar:
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)Pero esto siempre resulta en un error:
TypeError: test1() missing 1 required positional argument: 'category' Me doy cuenta de que podría convertir este ejemplo trivial en una función, y funcionaría. Preferiría usar TestCase de django porque incluye soporte para importar archivos tradicionales de "dispositivos de django" , que requieren varias de mis pruebas. Convertir mis pruebas en funciones requeriría volver a implementar esta lógica, ya que no hay una forma documentada de importar "dispositivos de django" con pytest (o pytest-django).
versiones del paquete :
Django==3.1.2 pytest==6.1.1 pytest-django==4.1.0Me resulta más fácil usar el enfoque "usefixtures". No muestra un segundo argumento mágico para la función y marca explícitamente la clase por tener accesorios.
@pytest.mark.usefixtures("category") class CategoryTest(TestCase): def test1(self): assert Category.objects.count() == 1Opté por reescribir la lógica de dispositivos de django utilizando un "dispositivo de prueba de pytest" que se aplica en el ámbito de la session . Todo lo que necesita es un solo accesorio en un archivo conftest.py en la raíz de su directorio de prueba:
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)Esto me permitió descartar por completo las pruebas basadas en clases y solo usar pruebas basadas en funciones.
¿Por qué necesita TestCase? Usualmente uso la clase Python y creo pruebas allí.
Ejemplo
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