Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test a Django model with pytest?

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.

like image 387
All Іѕ Vаиітy Avatar asked Apr 06 '16 09:04

All Іѕ Vаиітy


People also ask

Can we use pytest for Django?

pytest and pytest-django are compatible with standard Django test suites and Nose test suites. They should be able to pick up and run existing tests without any or little configuration. This section describes how to get started quickly.


1 Answers

pytest has support for running Python unittest.py style tests. It’s meant for leveraging existing unittest-style projects to use pytest features. Concretely, pytest will automatically collect unittest.TestCase subclasses and their test methods in test files. It will invoke typical setup/teardown methods and generally try to make test suites written to run on unittest, to also run using pytest.

The given tests can be tested with py.test without any modification, however py.test makes the tests more pythonic.

class SettingsTest(TestCase):    
    def test_account_is_configured(self):
        assert 'accounts' in INSTALLED_APPS
        assert '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):
        assert isinstance(self.test_user, User)

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

    def test_default_user_is_staff(self):
        assert not self.test_user.is_staff

    def test_default_user_is_superuser(self):
        assert not self.test_user.is_superuser

    def test_get_full_name(self):
        assert self.test_user.get_full_name() == 'Test User'

    def test_get_short_name(self):
        assert self.test_user.get_short_name() == self.email

    def test_unicode(self):
        assert self.test_user.__unicode__() == self.username

as @Sid mentioned, you can use the @pytest.mark.django_db marker (decorator) to access the database when running a test without using django.test.TestCase,

like image 174
x0x Avatar answered Oct 13 '22 18:10

x0x