Django Unit Testing - Как протестировать все экземпляры в модели?
Я хочу проверить все экземпляры в БД с помощью Django.
У меня есть скрипт python, который заполняет БД, и я хочу проверить каждый экземпляр, прошел ли он тест.
Я предоставляю здесь фиктивный tests.py:
from django.test import TestCase
from app_core.models import Item
# Item model fields are: pk, first, second
class PairTestCase(TestCase):
def setUp(self):
# This script populates the DB creating several Item instances
from app_core.init import init_items
def test_pair_elems_different(self):
"""First and second fields MUST be different inside the instance"""
item = Item.objects.get(pk=1)
self.assertNotEqual(item.first, item.second)
Как видите, я только что протестировал один экземпляр. Предположим, что БД содержит 1000 экземпляров элементов, какой лучший способ протестировать их все?
Единственное решение, которое приходит мне в голову, это использование простого цикла FOR внутри test_pair_elems_different, итерация всех объектов и сравнение каждого экземпляра.
Правилен ли такой подход в контексте лучших практик/принципов модульного тестирования?
Мне кажется, вы смотрите на это не с той стороны.
Вы хотите убедиться, что first != second
, верно? Предположительно, у вас есть ограничение на модель, и именно его вы проверяете.
Вам нужен тест, который пытается добавить запись, где эти 2 поля равны, затем проверить, что эта попытка вызывает соответствующую ошибку ограничения.
Я сам больше люблю pytest, но я думаю, что стандартный фреймворк unittest использует assertRaises
для этого.
Когда вы убедились, что добавление записи с одинаковыми значениями недопустимо, нет необходимости проверять каждый экземпляр.
Вы можете сделать что-то вроде этого. Аннотируйте столбец if these two fields are equal и затем отфильтруйте по нему.
Это фактически будет проверять каждый отдельный элемент, но это не даст вам ошибку, как Item <230> failed validation
, но даст вам общее Items Failed
from django.db.models import Q, F, ExpressionWrapper, BooleanField
countOfEqual = Item.objects.annotate(
equal=ExpressionWrapper(
Q(first=F('second')),
output_field=BooleanField()
)).filter(equal=True).count()
self.assertEqual(countOfEqual, 0, '{0} Items have matching first & second. This should be 0'.format(countOfEqual))
Если вам нужны конкретные предметы, которые не удались, вы можете, по крайней мере, отрезать .count()
и фильтровать по списку - это сократит время, поскольку вы будете перебирать только те предметы, о которых уже знаете, что они плохие