Search code examples
djangodjango-modelsdjango-testing

Django Model method test


I have model like this:

class Users(models.Model):
    pin = models.CharField(max_length=16, unique=True)
    name = models.CharField(max_length=64)
    surname = models.CharField(max_length=64, blank=True, null=True)
    patronymic = models.CharField(max_length=64, blank=True, null=True)

    def get_full_name(self):
        name = self.name
        surname = self.surname
        if self.surname is None:
            surname = ''
        if self.name is None:
            name = ''
        return str(name) + ' ' + str(surname)

I want to write a test case for get_full_name method. Currently I wrote something like this:

class TestUsersModel(TestCase):

    def setUp(self):
        self.data1 = Users.objects.create(name='Bob', pin='1')
        self.data2 = Users.objects.create(surname='Alex', pin='2')

    def test_users_model_entry(self):
        data = self.data1
        self.assertTrue(isinstance(data, Users))

    def test_users_full_name_only_name(self):
        data = self.data1.get_full_name()
        self.assertEquals(data,'Bob ')

    def test_users_full_name_only_surname(self):
        data = self.data2.get_full_name()
        self.assertEquals(data,' Alex')

but when I check with coverage it says me that I have to write test case for this: enter image description here

What I am missing here?


Solution

  • @sevdimali - Firstly, it is a bad idea to name a field as name and not first_name when you have the other field as surname. Also, if you decide to use first_name then the other field should be last_name. Consistency matters.

     class Users(models.Model):
        pin = models.CharField(max_length=16, unique=True)
        name = models.CharField(max_length=64,null=True)#or else you cannot test #object creation without name
        surname = models.CharField(max_length=64, blank=True, null=True)
        patronymic = models.CharField(max_length=64, blank=True, null=True)
    
    Now, to test your get_full_name(). How about we do something like this?
    
         def setUp(self):
             self.user = Users.objects.create(name='test', surname='world',pin='1234')
             self.user_without_surname = Users.objects.create(name='test',pin='12345')
             self.user_without_name=Users.objects.create(surname='world',pin='123456')
         
         def test_get_full_name_with_valid_name_and_surname(self):
             expected = str(self.user.name) + ' ' + str(self.user.surname)
             actual = 'test world'
             self.assertEquals(expected,actual)
         
         def test_get_full_name_with_empty_surname(self):
            expected = str(self.user.name) + ' ' +''
            actual = 'test '
            self.assertEquals(expected,actual)
         def test_get_full_name_with_empty_name(self):
            expected = '' + ' ' +str(self.user.surname)
            actual = ' world'
            self.assertEquals(expected,actual)
            
    

    Key things to refactor-

    1. IMO, the Model name should not be plural
    2. Name doesn't make sense. Be explicit. first_name,middle_name,last_name if needed
    3. Think about null columns and the consequences they might have. You don't want to have a user without even the first_name, last_name, email, and other essential fields.