I have a model:
class Trade(models.Model):
name = models.CharField(max_length=255, unique=True)
is_active = models.BooleanField('Active', default=True)
is_deleted = models.BooleanField('Deleted', default=False)
and views.py
class TradeViewSet(viewsets.ModelViewSet):
queryset = Trade.objects.all()
permission_classes = [permissions.IsAuthenticated]
serializer_class = TradeSerializer
filter_backends = [
DjangoFilterBackend,
CaseInsensitiveOrderingFilter,
SearchFilter
]
filter CaseInsensitiveOrderingFilter
class CaseInsensitiveOrderingFilter(OrderingFilter):
"""
Custom filter to order case insensitive fields as CharField and TextField.
To define filter it's needed to add char or text fields to list:
ordering_case_insensitive_fields = ["field"]
"""
def filter_queryset(self, request, queryset, view):
ordering = self.get_ordering(request, queryset, view)
insensitive_ordering = getattr(view, 'ordering_case_insensitive_fields', ())
if ordering:
new_ordering = []
for field in ordering:
if field.lstrip('-') in insensitive_ordering:
if field.startswith('-'):
new_ordering.append(Lower(field[1:]).desc())
else:
new_ordering.append(Lower(field).asc())
else:
new_ordering.append(field)
return queryset.order_by(*new_ordering)
return queryset
And simple serializer
class TradeSerializer(serializers.ModelSerializer):
class Meta:
model = models.Trade
fields = (
'id', 'name', 'is_active', 'is_deleted',
)
read_only_fields = ('is_deleted', 'id')
my tests.py
class TradeAPITest(BaseAPITestCaseSetup):
data = {
'name': 'Trade Name 012000',
'is_active': True,
}
def setUp(self):
super().setUp()
self.trade = Trade.objects.create(**self.data)
factories.TradeFactory.create_batch(10)
self.test_data = {
'name': 'Trade Name 2',
'is_active': True,
}
def test_ordering_by_name_ascending(self):
url = reverse('trades-list') + '?ordering=name'
response = self.client.get(url)
response_results = response.json().get('results')
expected_result = sorted(response_results, key=lambda i: i['name'].lower())
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response_results, expected_result)
def test_ordering_by_name_descending(self):
url = reverse('trades-list') + '?ordering=-name'
response = self.client.get(url)
response_results = response.json().get('results')
expected_result = sorted(
response_results, key=lambda i: i['name'].lower(), reverse=True
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response_results, expected_result)
I want to test if ordering is correct, for models generation I use factory with Faker Everything works fine locally. But in some cases, my tests don't pass the pipeline when I push to the repository.
self = <tests.trades.test_trades_base_views.TradeAPITest testMethod=test_ordering_by_name_descending>
def test_ordering_by_name_descending(self):
url = reverse('trades-list') + '?ordering=-name'
response = self.client.get(url)
response_results = response.json().get('results')
expected_result = sorted(
response_results, key=lambda i: i['name'].lower(), reverse=True
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
> self.assertEqual(response_results, expected_result)
E AssertionError: Lists differ: [{'id[451 chars]d': 57, 'name': 'I process environmental story[386 chars]lse}] != [{'id[451 chars]d': 52, 'name': 'Interview because data such d[386 chars]lse}]
E
E First differing element 5:
E {'id': 57, 'name': 'I process environmental story[38 chars]alse}
E {'id': 52, 'name': 'Interview because data such d[43 chars]alse}
I can't figure out what is a problem