mercredi 17 février 2021

How to test Django Custom Forms/Views with .save() and .is_valid() form methods

I'm developing a web application and beginning to write tests for an app within the project 'users'. I'm using Python Unit-Testing and TestCase with coverage.

I have approximately 83% tested so far however I can't seem to figure out how I should be testing the form.save() method. In addition to this, form.is_valid() seems to never be evaluating to true in my views.py file shown below:

Views.py

from django.shortcuts import render, redirect
from users.forms import RegistrationForm, LoginForm
from django.contrib import messages
from django.contrib.auth import login, logout, authenticate


# Register view
def user_register(response):
    if response.method == 'POST':
        form = RegistrationForm(response.POST)
        if form.is_valid():
            # Can be saved once valid
            form.save()
            # Clean inputs
            username = form.cleaned_data.get('username')
            email = form.cleaned_data.get('email')
            password = form.cleaned_data.get('password1')
            first_name = form.cleaned_data.get('first_name')
            last_name = form.cleaned_data.get('last_name')
            messages.success(response, f'Account created for {username}')
            return redirect('home')
    else:
        form = RegistrationForm()

    return render(response, 'users/register.html', {'form': form})

I can't post an image here but running coverage with live-server, it shows that everything after the 'if form.is_valid()' is highlighted in red as too is the single line in the else condition 'form = RegistrationForm()'

This is my testing code:

test_views.py

from django.test import TestCase, Client
from django.urls import reverse
from django.contrib.auth import get_user_model
from users.forms import RegistrationForm

...
...

class RegisterViewsTest(BaseViewsTest):
    def test_form_save_POST(self):
        form_data = {
            'username': 'johndoe',
            'email': 'dean@mail.com',
            'password1': 'testuserpassword123',
            'password2': 'testuserpassword123'
        }
        form = RegistrationForm(form_data)
        self.assertTrue(form.is_valid())
        self.assertFalse(form.save())

I'm new enough to testing in Django/Python so I'm not all too familiar with how to test forms especially custom forms and views.

Below is the model I am using for a user:

models.py

from django.contrib.gis.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin


# Overide auth_user model with custom properties
# User management class
class UserManagement(BaseUserManager):

    def create_user(self, email, username, password, **kwargs):
        if not email:
            raise ValueError("Email address is required")
        if not username:
            raise ValueError("Username is required")
        if not password:
            raise ValueError("Password is required")

        # Fill the model with parameter data
        email = self.normalize_email(email)
        user = self.model(
            email=email,
            username=username,
            **kwargs
        )

        user.set_password(password)
        user.save()
        return user

    def create_staffuser(self, email, username, password, **kwargs):
        # Set defaults for staffuser account
        kwargs.setdefault('is_staff', True)
        kwargs.setdefault('is_superuser', False)
        kwargs.setdefault('is_active', True)

        if kwargs.get('is_staff') is not True:
            raise ValueError('Staff must be assigned Staff permissions')
        if kwargs.get('is_active') is not True:
            raise ValueError('Creating a new user must immediately make that user active.')
        if kwargs.get('is_superuser') is not False:
            raise ValueError('There must only be one superuser within this system')

        user = self.create_user(
            email=self.normalize_email(email),
            username=username,
            password=password,
            **kwargs
        )

        user.save(using=self._db)
        return self.create_user(email, username, password, **kwargs)


# Define a user
class User(AbstractBaseUser, PermissionsMixin):
    # Custom model elements
    username = models.CharField('Username', primary_key=True, max_length=150)
    password = models.CharField('User Password', null=False, max_length=150)
    first_name = models.CharField('First Name', null=True, max_length=50)
    last_name = models.CharField('Last Name', null=True, max_length=50)
    country = models.CharField('Country', blank=True, null=True, max_length=56)  # longest country name is 56 chars

    # Required for method overide
    date_joined = models.DateTimeField('Date Joined', auto_now_add=True, null=True)
    last_login = models.DateTimeField('Last Login', auto_now_add=True, null=True)
    is_admin = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    email = models.EmailField('Email Address', null=False, max_length=150, unique=True)

    # Type objects
    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['email']

    objects = UserManagement()

    def __str__(self):
        return f"{self.username}"

I was hesitant to post here and tried looking up various tutorials and reading Django docs but I'm not finding out much very quick and I'm under a lot of time pressure with this.

Any help at all appreciated, thank you :)

Aucun commentaire:

Enregistrer un commentaire