How to Add Unit Testing in Django?

Hi Dev,
I am going to explain you example of how to implement unit testing in django?. I would like to share with you how to write unittest in django. I explained simply step by step how to write and run unittest in django. Here you will learn how to run unittest in django. you will do the following things for how to add unit testing in django.
The process of developing software must include testing. Many programmers skip this step and test their code by hand instead.
As the size of the programme increases, manual code testing gets tiresome. Every component you add to your programme must function properly without affecting the operation of other features, and unit tests make sure this happens.
In this straightforward illustration, we'll test:
- test_api_view.py
- test_forms.py
- test_models.py
- test_views.py
Here i explained simply step by step example of how to write unittest in django.
Step 1: Create a Project
In this step, we’ll create a new django project using the django-admin. Head back to your command-line interface and run the following command:
django-admin startproject example
Step 2: Create a App
Now we'll create a single app called core to store a list of post names. We're keeping things intentionally basic. Stop the local server with Control+c and use the startapp command to create this new app.
python3 manage.py startapp core
Step 3: Install a Django REST Framework
First of all let’s install django and djangorestframework which are the necessary Python libraries.Django Rest Framework.
pip install djangorestframework
Step 4: Update setting.py
Then update INSTALLED_APPS within our settings.py file to notify Django about the app, in setting.py file so our setting file look like this..
settings.py.... INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'core', 'rest_framework', ]
Step 5: Create a Model
Now go for the models we will We'll call our single model Student and it will have define below all fields: first_name and last_name is a full name of string return. And finally set __str__ to display the name of the student in admin interface.
core/models.pyfrom django.db import models from django.urls import reverse # Create your models here. class Student(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) reg_number = models.CharField(max_length=50) date_of_admission = models.DateField(null=True, blank=True) class Meta: ordering = ['-id'] def get_absolute_url(self): return reverse("student_detail", args=[str(self.id)]) def __str__(self): return f"Name: {self.first_name} {self.last_name}"
Ok, all set. We can engender a migrations file for this change, then integrate it to our database via migrate.
python manage.py makemigrations python manage.py migrate
Step 6: Creating the Serializers
In this step, we need to create Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON, XML or other content types. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data. Let’s start creating a serializer.
core/serializers.pyfrom rest_framework import serializers from .models import Student class StudentSerializer(serializers.ModelSerializer): class Meta: model = Student fields = "__all__"
The bit of code above transforms the Student model into a JSON and back again. Transmission of JSON data via HTTP is simple. The data is transformed to JSON for this reason.
Step 7: Creating the Views
In this step, we need to configure views. The StudentListView will just return a list of all student. open the core/views.py file and add:
core/views.pyfrom django.shortcuts import render from .models import Student from django.core.paginator import Paginator from django.views.generic import DetailView from django.views.generic.list import ListView # Create your views here. class StudentListView(ListView): model = Student template_name = 'student.html' paginate_by = 10 class StudentView(DetailView): model = Student
Step 8: Creating API Views
Add the following code snippets to a new python file called api views.py in the testing application.
core/views.pyfrom rest_framework import generics from .models import Student from .serializers import StudentSerializer class CreateStudentApiView(generics.CreateAPIView): queryset = Student.objects.all() serializer_class = StudentSerializer
A class that enables the creation of students using a REST API is present in the aforementioned code snippets.
Step 9: Creating the Templates
Next, then with your text editor create new templates files: core/templates/student.html file and the add:
core/templates/student.html<!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> <title>Tuts-Station.com</title> </head> <body> <div class="container" style="margin-top: 100px;"> <table class="table"> <thead class="thead-dark"> <tr> <th scope="col">#</th> <th scope="col">First</th> <th scope="col">Last</th> <th scope="col">Reg. No.</th> </tr> </thead> <tbody> <!-- prints out the students details in a table --> {% for student in student_list %} <tr> <th scope="row">{{ student.id }}</th> <td>{{ student.first_name }}</td> <td>{{ student.last_name }}</td> <td>{{ student.reg_number }}</td> </tr> {% endfor %} </tbody> </table> </div> <!-- Optional JavaScript --> <!-- jQuery first, then Popper.js, then Bootstrap JS --> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script> </body> </html>
Step 10: Writing Unit Tests
Writing tests for our beliefs will be the first step. Make a new tests-themed Python package and include it in the testing application.
Testing Views:
core/tests_views.pyfrom django.test import TestCase from core.models import Student from django.urls import reverse class StudentListViewTest(TestCase): @classmethod def setUpTestData(cls): number_of_students = 30 for student_id in range(number_of_students): Student.objects.create(first_name=f"John{student_id}", last_name=f"Doe{student_id}") def test_url_exists(self): response = self.client.get("/students") self.assertEqual(response.status_code, 200) def test_url_accessible_by_name(self): response = self.client.get(reverse('students')) self.assertEqual(response.status_code, 200) def test_view_uses_correct_template(self): response = self.client.get(reverse('students')) self.assertEqual(response.status_code, 200) self.assertTemplateUsed(response, 'student.html') def test_pagination_is_correct(self): response = self.client.get(reverse('students')) self.assertEqual(response.status_code, 200) self.assertTrue('is_paginated' in response.context) self.assertTrue(response.context['is_paginated'] is True) self.assertEqual(len(response.context['student_list']), 10)
Testing Models:
core/tests_views.pyfrom core.models import Student from django.urls import reverse from django.test import TestCase class StudentModelTestcase(TestCase): @classmethod def setUpTestData(cls): Student.objects.create(first_name="Bhavesh", last_name="Sonagra", reg_number="1111") def test_string_method(self): student = Student.objects.get(id=1) expected_string = f"Name: {student.first_name} {student.last_name}" self.assertEqual(str(student), expected_string) def test_get_absolute_url(self): student = Student.objects.get(id=1) self.assertEqual(student.get_absolute_url(), "/students/1")
Testing Forms:
First of all in this step we will create a new file called forms.py and create a Django form you need to use Django Form Class
core/forms.pyfrom django import forms class StudentForm(forms.ModelForm): class Meta: model = Student fields = ('first_name', 'last_name', 'reg_number')core/tests_views.py
from core.models import Student from django.urls import reverse from django.test import TestCase from core.forms import StudentForm class StudentModelTestcase(TestCase): @classmethod def test_valid_form(self): w = Student.objects.create(first_name="Bhavesh", last_name="Sonagra", reg_number="1111") data = {'first_name': w.first_name, 'last_name': w.last_name, 'reg_number': w.reg_number} form = StudentForm(data=data) self.assertTrue(form.is_valid(),True) def test_invalid_form(self): w = Student.objects.create(first_name="Bhavesh", last_name="", reg_number="") data = {'first_name': w.first_name, 'last_name': w.last_name, 'reg_number': w.reg_number} form = StudentForm(data=data) self.assertFalse(form.is_valid())
Testing API Views:
core/tests_views.pyfrom core.models import Student from django.urls import reverse from rest_framework.test import APITestCase class StudentSerializerTestCase(APITestCase): def student_creation_test(self): payload = { "first_name": "Bhavesh", "last_name": "Sonagra", "reg_number": "123456", "date_of_admission": datetime.date.today() } response = self.client.post(reverse("student_create"), payload) self.assertEqual(status.HTTP_201_CREATED, response.status_code)
Step 11: Creating URLs
In this section, we need a urls.py file within the core app however Django doesn't create one for us with the startapp command. Create core/urls.py with your text editor and paste below code.
core/urls.pyfrom django.urls import path from . import views from .api_view import CreateStudentApiView urlpatterns = [ path('students', views.StudentListView.as_view(), name="students"), path('students/create', CreateStudentApiView.as_view(), name="create_student"), path('students/<int:id>', views.StudentView.as_view(), name="student_detail"), ]
Next, we require to add a URL path for our example app which can be done by importing include and setting a path for it.
example/urls.pyfrom django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('core.urls')), ]
Run the Test
Run the command shown below in the terminal's current working directory to run our tests.
python manage.py testOutput
Creating test database for alias 'default'... System check identified no issues (0 silenced). ........ ---------------------------------------------------------------------- Ran 8 tests in 0.032s OK Destroying test database for alias 'default'...
I hope it will help you....
Happy Coding!