3

I'm building an authentication system for a website, I don't have prior test experience with Django. I have written some basic tests.

the model,

class User(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(max_length=25, unique=True, error_messages={
        'unique': 'The username is taken'
    })
    first_name = models.CharField(max_length=60, blank=True, null=True)
    last_name = models.CharField(max_length=60, blank=True, null=True)
    email = models.EmailField(unique=True, db_index=True, error_messages={
        'unique': 'This email id is already registered!'
    })

    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    date_joined = models.DateTimeField(auto_now_add=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username',]


    objects = UserManager()

    def get_full_name(self):
        return ' '.join([self.first_name, self.last_name])

    def get_short_name(self):
        return self.email

    def __unicode__(self):
        return self.username

and model manager,

class UserManager(BaseUserManager):
    def create_user(self, email, password=None, **kwargs):
        if not email:
            raise ValueError('Enter Email address')

        if not kwargs.get('username'):
            raise ValueError('Enter Username')

        account = self.model(
            email=self.normalize_email(email), username=kwargs.get('username')
        )

        account.set_password(password)
        account.save()

        return account

    def create_superuser(self, email, password, **kwargs):
        account = self.create_user(email, password, **kwargs)

        account.is_superuser = True
        account.save()

        return account

and my tests,

class SettingsTest(TestCase):    
    def test_account_is_configured(self):
        self.assertTrue('accounts' in INSTALLED_APPS)
        self.assertTrue('accounts.User' == AUTH_USER_MODEL)


class UserTest(TestCase):
    def setUp(self):
        self.username = "testuser"
        self.email = "testuser@testbase.com"
        self.first_name = "Test"
        self.last_name = "User"
        self.password = "z"

        self.test_user = User.objects.create_user(
            username=self.username,
            email=self.email,
            first_name=self.first_name,
            last_name=self.last_name
        )


    def tearDown(self):
        del self.username
        del self.email
        del self.first_name
        del self.last_name
        del self.password

    def test_create_user(self):
        self.assertIsInstance(self.test_user, User)

    def test_default_user_is_active(self):
        self.assertTrue(self.test_user.is_active)

    def test_default_user_is_staff(self):
        self.assertFalse(self.test_user.is_staff)

    def test_default_user_is_superuser(self):
        self.assertFalse(self.test_user.is_superuser)

    def test_get_full_name(self):
        self.assertEqual('Test User', self.test_user.get_full_name())

    def test_get_short_name(self):
        self.assertEqual(self.email, self.test_user.get_short_name())

    def test_unicode(self):
        self.assertEqual(self.username, self.test_user.__unicode__())

fortunately all the passes, and my question is, are these tests overdone or underdone or normal? What should be tested in a model? is there any procedure missing? anything wrong with this tests?? how do I effectively write tests??

thank you for any insights.

All Іѕ Vаиітy
  • 24,861
  • 16
  • 87
  • 111
  • In `tearDown(self)` probably do `self.test_user.delete()`, because if you'd run the test with `--keepdb` flag, it would try to create the user again with the same email and fail. – C14L Feb 19 '16 at 22:51
  • Definitely not the end-game, but it's usually worth using coverage to try and get 100% statements hit in your tests. It's usually not too difficult in relatively small Django projects to do. I find it's less about finding any bugs hiding on hidden lines, but more about inspiration for new test cases. https://coverage.readthedocs.org/en/coverage-4.0.3/ – DaveBensonPhillips Feb 20 '16 at 06:57
  • I'm just going to link to this SO answer, as it appears the tests code is the same as here. It is public domain, but worth crediting https://stackoverflow.com/a/36567915/943773 – ryanjdillon Oct 10 '18 at 12:11

1 Answers1

5

That's quite enough. Just a couple of notes:

  1. No need to delete properties in tearDown
  2. You forgot to tests UserManager in lines raise ValueError using assertRaises.
  3. You may also test that user created by create_user(from UserManager) can authenticate(from django.contrib.auth) by given password and email.
  4. Use coverage package to detect which lines/classes/packages/statements were missed to test.
Benyamin Jafari
  • 27,880
  • 26
  • 135
  • 150
Albert Tugushev
  • 1,504
  • 13
  • 25