I want to test all instances in a DB using Django.
I have a python script that populates the DB and I want to test every single instance if it pass the test.
I provide here a dummy 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)
As you can see, I just tested a single instance. Let's suppose the DB contains 1000 Item instances, what is the best way to test them all?
The only solution that pops up in my mind is using a simple FOR loop inside test_pair_elems_different, iterating all object and comparing each instance.
Is this approach correct in the context of unit testing best practices/principles?
CodePudding user response:
I think you're looking at this the wrong way around.
You want to ensure first != second
, right? Presumably you have a constraint on the model and it's this you're testing.
What you want is a test that tries to add a record where these 2 fields are equal, then test that this attempt raises the approriate constraint error.
I'm more of a pytest person myself, but I think the standard unittest framework uses assertRaises
for this.
When you've validated that adding a record with equal values is not allowed, there is no need to go and test every instance.
CodePudding user response:
You could do something like this. Annotate a Column of if those two fields are equal and then filter by it.
This in fact would test every single item, but it wouldn't give you an error like Item <230> failed validation
, but it'll give you a general 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))
If you did want specific items that failed you could at least chop off the .count()
and filter through the list- this would cut down on time as you're only looping through items you already know are bad