3

I have the following test which fails as it only inserts one row into the database where it should be inserting 100 rows

class QuestionsTest(TestCase):
    def setUp(self):
        self.fake = Faker()

    def test_populating_table_with_random_data(self):
        newQuestion = Questions()
        x = 0
        while x < 100:
            newQuestion.category = self.fake.text(max_nb_chars=254)
            newQuestion.difficulty = self.fake.text(max_nb_chars=8)
            newQuestion.question_type = self.fake.text(max_nb_chars=20)
            newQuestion.text = self.fake.text(max_nb_chars=254)
            newQuestion.save()
            x += 1
        #100 rows should be inserted
        self.assertEqual(Questions.objects.count(), (100))


"""Traceback (most recent call last):
  File 'Database/tests.py', line 99, in test_populating_table_with_random_data
    self.assertEqual(Questions.objects.count(), (100))
AssertionError: 1 != 100 """


Prior to receiving this error I was getting the error "Class Questions has no objects member". I got around this by explicitly declaring

objects = models.Manager()

in my Questions model, but I thought that django automatically generated a manager with the name objects

1 Answers1

3

You each time save the same Questions object, so after creating it the first time, you update the existing object. At the end, there is only one.

You can create a new object in the loop:

class QuestionsTest(TestCase):
    def setUp(self):
        self.fake = Faker()

    def test_populating_table_with_random_data(self):
        x = 0
        while x < 100:
            newQuestion = Questions()
            newQuestion.category = self.fake.text(max_nb_chars=254)
            newQuestion.difficulty = self.fake.text(max_nb_chars=8)
            newQuestion.question_type = self.fake.text(max_nb_chars=20)
            newQuestion.text = self.fake.text(max_nb_chars=254)
            newQuestion.save()
            x += 1
        #100 rows should be inserted
        self.assertEqual(100, Questions.objects.count())

It is probably better to use a for loop:

class QuestionsTest(TestCase):
    def setUp(self):
        self.fake = Faker()

    def test_populating_table_with_random_data(self):
        for __ in range(100):
            newQuestion = Questions()
            newQuestion.category = self.fake.text(max_nb_chars=254)
            newQuestion.difficulty = self.fake.text(max_nb_chars=8)
            newQuestion.question_type = self.fake.text(max_nb_chars=20)
            newQuestion.text = self.fake.text(max_nb_chars=254)
            newQuestion.save()
        #100 rows should be inserted
        self.assertEqual(100, Questions.objects.count())

You can also create the object with .objects.create(…):

class QuestionsTest(TestCase):
    def setUp(self):
        self.fake = Faker()

    def test_populating_table_with_random_data(self):
        for __ in range(100):
            newQuestion = Questions.objects.create(
                category = self.fake.text(max_nb_chars=254),
                difficulty = self.fake.text(max_nb_chars=8),
                question_type = self.fake.text(max_nb_chars=20),
                text = self.fake.text(max_nb_chars=254)
            )
        #100 rows should be inserted
        self.assertEqual(100, Questions.objects.count())
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555
  • Your answer worked perfectly. Would you be able to elaborate on why it would be better to use `for` over `while` and is there any specific reason you used `__` in the for loop – 0kImightBeAble Jun 05 '20 at 18:04
  • @0kImightBeAble: because it is harder to get in an infinite loop with a `for`, since it keeps iterating over the iterable. You do not need to initialize, check and update the variable. The `__` is often used as a "throw away" variable, so a variable we do not care about, but have to use to make it valid Python. – Willem Van Onsem Jun 05 '20 at 19:03