Как протестировать методы в models.py, связанные с фильтрами в django, используя pytest?
У меня есть модели, которые содержат множество classmethods для фильтрации различных типов данных. Проблема в том, что эти методы вызываются в представлениях для нескольких функций. Например, у меня есть таблица заказов, как показано ниже:
class Order(models.Model):
user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
total = models.DecimalField(max_digits=12, decimal_places=2, default=0)
order_date = models.DateTimeField(auto_now_add=True)
cancelled = models.BooleanField(default=False)
items = models.ManyToManyField(Items, through='OrderItems')
status = models.CharField(max_length=30, choices=choice_status, default='waiting')
restaurant = models.ForeignKey(Restaurant, on_delete=models.SET_NULL, related_name='orders', null=True)
razorpay_payment_id = models.CharField(max_length=100, null=True, blank=True)
razorpay_order_id = models.CharField(max_length=100, null=True, blank=True)
mode = models.CharField(max_length=10, choices=choice_mode, default='COD', null=True, blank=True)
paid = models.BooleanField(default=False, null=True, blank=True)
delivery_charges = models.DecimalField(max_digits=12, decimal_places=2, default=0)
user_address = models.TextField(max_length=500)
user_address_lat = models.DecimalField(max_digits=9, decimal_places=6)
user_address_long = models.DecimalField(max_digits=9, decimal_places=6)
restaurant_address = models.TextField(max_length=500)
restaurant_address_lat = models.DecimalField(max_digits=9, decimal_places=6)
restaurant_address_long = models.DecimalField(max_digits=9, decimal_places=6)
@classmethod
def get_order_with_search_params(cls, params, queryset):
search_order_id = None
with contextlib.suppress(ValueError):
search_order_id = int(params)
return queryset.filter(
Q(user__username__icontains=params) |
Q(restaurant__name__icontains=params) |
Q(id=search_order_id)
)
@classmethod
def get_order_from_status(cls, params, queryset):
return queryset.filter(Q(status=params.lower()))
@classmethod
def get_order_from_restaurant_id(cls, params, queryset):
restaurant_id = None
with contextlib.suppress(ValueError):
restaurant_id = int(params)
return queryset.filter(Q(restaurant_id=restaurant_id))
@classmethod
def get_object_from_pk(cls, pk):
return get_object_or_404(cls, pk=pk)
@classmethod
def get_total_of_all_orders(cls, queryset=None):
if not queryset:
queryset = cls.objects.all()
return queryset.filter(status='delivered').aggregate(total_sum=Sum('total'))['total_sum']
Теперь, чтобы протестировать эти функциональные возможности, я должен сначала сделать следующее:
зарегистрировать пользователя (тип ресторана)
активировать этого пользователя
добавить предметы в магазин с пользователем ресторана
зарегистрировать другого пользователя (тип клиента)
активировать и этого пользователя
добавить товар в корзину
оформить заказ
После размещения заказа будет создан объект Order, затем я могу протестировать функциональные возможности, такие как фильтр. Таким образом, это интеграционное тестирование.
Кроме того, на этих шагах затрагиваются многие связанные таблицы, например, при регистрации пользователей будет создана таблица Address, при добавлении товаров будет заполнена таблица CartItem, и многое другое. По этой причине я не могу просто использовать Order.objects.create(**kwargs)
и затем протестировать classmethods
модели. Должен ли я пропустить тестирование этих методов класса? Или есть другие способы протестировать эти методы?
Для справки: я создал тесткейсы только для полей и методов str, показанных ниже
def test_str_method(self):
obj = State.objects.create(name='TestState')
assert str(obj) == obj.name
def test_document_data(self, get_agent_document_form_initial_data):
agent = User.objects.create(
**{'username': 'test_agent1', 'mobile_number': '+917894541211', 'email': 'test_agent1@gmail.com'})
document_obj = Document.objects.create(agent=agent,
**get_agent_document_form_initial_data(pancard_document=filename,
license_document=filename))
assert document_obj.agent == agent
# assert document_obj.id == 1
assert document_obj.is_verified is False
assert document_obj.account_no == 1234567890
assert document_obj.ifsc_code == 'ABCD0123456'
assert document_obj.pancard_number == 'BNZAA2318J'
assert document_obj.ifsc_code == 'ABCD0123456'
assert document_obj.license_number == 'HR-0619850034761'
assert document_obj.pancard_document == './media/default.jpg'
assert document_obj.license_document == './media/default.jpg'
assert document_obj.razorpay_contact_id is None
assert document_obj.razorpay_fund_account_id is None
assert str(document_obj) == f'{document_obj.id} | {document_obj.agent} | {document_obj.is_verified}'
Просто проверка правильности значений полей. Но я хочу написать тесткейсы для других методов в моделях, которые связаны с потоком проекта.
Вы можете предварительно заполнить данные в базе данных, для лучшего понимания вы можете перейти по ссылке this.
А затем просто протестируйте свой метод, как показано ниже:
class TestOrderModelMethods:
def test_get_order_from_status(self):
assertQuerysetEqual(
Order.get_order_from_status(params='waiting', queryset=Order.objects.all()),
Order.objects.filter(status='waiting'),
ordered=False)