Search code examples
pythondjangodjango-modelsdjango-tests

writing djnago test for __str__ in a model


I want to test my blog app. After running coverage, I have about 91% with 4 missing. The coverage pointed out the lines of code below to be missing.

def publish(self):
        self.published_date=timezone.now()
        self.save()

    def __str__(self):
        return self.title

Thus, I decided to write a test for str(self).

Here is what the test looks like

class PostTest(TestCase):

    def create_post(self, title="only a test", text="Testing if the created title matches the expected title"):
        return Post.objects.create(title=title, text=text, created_date=timezone.now())

    def test_post_creation(self):
        w = self.create_post()
        self.assertTrue(isinstance(w, Post))
        self.assertEqual(str(w), w.title)

The test fails with the following error.

django.db.utils.IntegrityError: null value in column "author_id" violates not-null constraint
DETAIL:  Failing row contains (1, only a test, Testing if the created title matches the expected title, 2020-05-31 05:31:21.106429+00, null, null, 0, null, 2020-05-31 05:31:21.108428+00, ).

This is what the model looks like:

class Post(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    slug = models.SlugField(max_length=200, unique=True, blank= True, null=True)
    updated_on = models.DateTimeField(auto_now= True)
    text = models.TextField()
    created_date = models.DateTimeField(default=timezone.now)
    published_date = models.DateTimeField(blank=True, null=True)
    status = models.IntegerField(choices=STATUS, default=0)
    photo = models.ImageField(upload_to='photos/%Y/%m/%d/', blank=True)

    class Meta:
        ordering = ['-published_date']

    def publish(self):
        self.published_date=timezone.now()
        self.save()

    def __str__(self):
        return self.title

How do you suggest I write the test to fix this error and improve the coverage?


Solution

  • The problem is that you need to pass an author to create a post:

    class PostTest(TestCase):
        def create_post(self, title="only a test", text="Testing if the created title matches the expected title"):
            # The arguments passed to initialize the user depend on your User model
            author = User.objects.create(username='username', first_name='first_name', last_name='last_name', email='email@gmail.com' password='Password0')
            return Post.objects.create(title=title, text=text, created_date=timezone.now())
    
        def test_post_creation(self):
            w = self.create_post()
            self.assertTrue(isinstance(w, Post))
            self.assertEqual(str(w), w.title)