How to test a Django model with pytest?

All Іѕ Vаиітy picture All Іѕ Vаиітy · Apr 6, 2016 · Viewed 9.8k times · Source

I am getting started with pytest. I have configured pytest, anyway I couldn't found a resource on Django specific testing with pytest. How do I test a model with pytest_django?

I have already asked a question on unittesting,

how do I efficiently test this Django model?

I want know how the same tests can be written with py.test?

adding below the model and the tests written in unittest.

the model under test is,

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 the unittest written,

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 = "[email protected]"
        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 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__())

Thank you for any inputs.

Answer

Sid picture Sid · Apr 8, 2016

You can use this plugin that integrates pytest with Django: https://pytest-django.readthedocs.org/en/latest/tutorial.html

The setup and changes to pytest.ini are described here: http://www.johnmcostaiii.net/2013/django-projects-to-django-apps-converting-the-unit-tests/

You will find your example here starting from slide 57. This deck will be useful in testing views as well as models and the settings specific to testing models: https://speakerdeck.com/pelme/testing-django-applications-with-py-dot-test-europython-2013

Specifically look at @pytest.mark.django_db helper documented here: http://pytest-django.readthedocs.org/en/latest/helpers.html

An example for allowing db access in a test also mentioned in the deck above is copied here. Without mark.django_db the test would fail.

import pytest
@pytest.mark.django_db
def test_user_count():
    assert User.objects.count() == 0