Test-Driven Development (TDD) is a technique in software development in which tests are developed first, followed by source code. The following bullet points are used to summarize its workflow:
- Tests are written first — they can’t pass since the source code they’re supposed to test doesn’t exist yet.
- The source code is written to fulfill the requirements specified in the tests.
- The tests have been completed.
- If they pass, it means the source code satisfies the test’s requirements.
- The source code is refactored to suit the requirements of the tests fail.
- For each test, repeat the instructions above.
TDD in Django
TDD appears to be counter-intuitive. So, why would you want to utilize it? It turns out there are several compelling reasons to do so. Consider the following points:
- TDD is defined as expressing requirements in terms of test cases. Following that, source code is written to meet those requirements. When all tests pass, you can rest assured that the criterion has been completed. Developers may avoid scope creep with this kind of attention.
- TDD can boost developer productivity by reducing development time. Working on individual requirements at a time reduces the number of variables involved. To code, you use manageable increments. As a result, you can efficiently resolve breaking changes and track them. The amount of time spent debugging is reduced. As a result, efficiency improves, and more time is dedicated to development.
- The tests are written with the needs of the users in mind. As a result, they are more likely to be produced with a specific goal in mind. These tests can provide adequate documentation for a codebase.
- Writing tests first ensures that your source code includes tests at all times. Furthermore, when the code base increases, test coverage is constantly maintained at an acceptable percentage.
TDD, on the other hand, isn’t a panacea! There are times when it isn’t ideal, such as when you’re working on a project.
When creating a proof of concept – for example, at a hackathon, tests are secondary. Tests are frequently not a priority because of the customary time constraints involved with such events.
When the required specs are not concise, the application’s requirements may become more apparent as development advances. Any tests written in this situation may become obsolete. As a result, more time is spent cleaning up the test suite than working on development.
A High-Level Overview of Django
Django describes itself as a “web framework for deadline-driven perfectionists.” It’s a Python framework, and it’s terrific and enjoyable to work with, just like most other Python libraries.
Django comes with views and templates, mostly HTML pages, models that map to your database tables, and a slew of additional out-of-the-box features detailed in their topic guide.
The documentation for Django is among the best and most valuable of any library or framework.
Installations
We must first install Python before we can use Django. For this tutorial, we’ll be using Python 3.9.
Python 3.9 installation
Install Python according to the instructions on the official Python page for your platform. Then, open the terminal to verify that the installation was successful and type the following.
python -V
The outcoming should be somehow similar to the screenshot below if the installation is successful.
Virtual environment
The rule of thumb is to create a virtual environment for each project before installing Django or most other Python libraries, for that matter.
As described, a virtual environment is a subdirectory on your computer where you can install project-specific requirements. It allows us to separate environments belonging to different projects on a single machine. We can escape dependency hell by using virtual environments.
For this post, virtualenv will suffice. Run the following command.
pip install virtualenv
There are simply three commands that we need to master;
1) The command virtualenv is used to create a virtual environment
virtualenv temp_env
2) The source command is used to activate a virtual environment.
source env/bin/activate
3) The command for deactivating a virtual environment
deactivate
Django can now be installed within the env virtual environment.
Django installation
Django 4.0 is used because it is the latest during this writeup.
We need to set up a repository(temperature_converter) and where our application’s code will live after installing Django. It is also possible to do this before installing Django -it is all up to you to choose.
mkdir temperature_converter
After that, we open a terminal and go to the temperature converter folder.
cd temperature_converter/
In the prompt of your terminal, ALWAYS put the name of the virtual environment in brackets when activating it. It is how our prompt appears.
(temp_env) ➜ temperature_converter
We can now give a quick summary of the project we want to develop now that Django is installed.
The App — A Temperature Conversion Tool
We hope to have proven how to utilize TDD to create a Django application by the end of this article. A temperature converter is an application in question. It has been chosen because temperature conversion is a simple idea to grasp, yet it leaves us a lot of opportunities for further TDD and testing.
We’ll concentrate on converting between Celcius to Fahrenheit units of temperature.
Creating the “Temperature Converter” project
We must first create a Django project before starting a Django app. Django projects are made up of Django apps. With the directory temperature_converter, we create a project.
django-admin startproject temperature_converter .
The converter project is created in the current directory as indicated by the period character that ends the command above. Your converter directory should have these contents up to this point.
Creating an App called ‘temperature’
Django projects contain Django apps. Let’s start by creating a temperature app within the temperature_converter project.
django-admin startapp temperature
The temperature app is now included in the converter’s directory structure.
Setting up the App
We can modify some settings to get the app ready for development. To begin, we’ll add the temperature app to the INSTALLED_APPS list. temperature_converter/settings.py contains this setting.
INSTALLED_APPS = [ . . . 'temperature,' ]
After that, we’ll make a blank URL file for our temperature app. Any URL is used to process temperature conversion requests will be saved here.
touch temperature/urls.py
After that, in temperature_converter/urls.py, add a reference to temperature/urls.py. Because of the reference to temperature.urls, the temperature_converter project is aware of any URLs related to a temperature conversion.
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('temperature.urls')), ]
We’re now ready to start working on our temperature converter app with TDD!
Writing Unit Tests
The converter app’s specs are rather well stated. All that is required of the software is to translate between different units of measurement.
TDD is used with well-defined specs.
In temperature/tests.py, we will define our unit tests. First, we’ll create the TestTemperatureConversion class. It will include unit tests involving temperature measurement conversions.
from django.test import TestCase, Client from django.urls import reverse class TestTemperatureConversion(TestCase): """ This class contains tests that convert temperature from Celcius to Fahrenheit. """ def setUp(self): """ It runs before any execution in each test case. """ self.client = Client() self.url = reverse("temperature:temperature-conversion")
We’ll import the Client class at the top of temperature/tests.py. It is a testing browser that allows Django tests to make http requests. When the URL’s name is handed in as an input, the reverse function is imported to produce a URL. We can now write tests based on our needs.
Requirement 1: Convert Celcius to Fahrenheit
Inside TestTemperatureConversion, let’s write a unit test for this requirement.
class TestTemperatureConversion(TestCase): def test_celcius_to_fahrenheit_conversion(self): """ Tests conversion of celcius to fahrenheit. """ celsius_1 = 25.8 data = { "temperature_in_celcius": celsius_1, } response = self.client.get(self.url, data) self.assertContains(response, 78.44)
Our application is expected to convert 25.8 Celcius to 78.44 Fahrenheit in the test (2 decimal places). Because the source code does not yet exist, running the tests will fail.
python manage.py test temperature
Only by converting Celcius to Fahrenheit will we fix this test.
Writing source code to convert degrees Celcius to Farenheit
The following is a simple approach to deal with unit conversions:
- Get the input value in degrees Celcius
- Convert the supplied value to the Farehnheit temperature equivalent of the temperatures in degrees Celcius.
- Return the resultant temperature in Farenheit.
Emphasis is now shifted to the temperature/view.py file. The code to convert temperature from Celcius to Fahrenheit is added here. We also specify how available measurement units are translated from Celcius. It will help us with the conversions. Add the following content to a file called temperature/views.py.
from django.shortcuts import render from django.http import JsonResponse def convert(request): temp_in_celcius =float(request.GET.get('temperature_in_celcius')) temp_in_fahrenheit= float((temp_in_celcius * 9/5) + 32) data = { 'temp_in_fahrenheit': temp_in_fahrenheit, } return JsonResponse(data)
Finally, the convert view must be mapped to a URL. Add the following to a file called temperature/urls.py:
from django.urls import path from .views import convert app_name = 'temperature' urlpatterns = [ path('temperature/', convert, name='temperature-conversion'), ]
Now it’s time to run the test with the logic to convert Celcius to Fahrenheit.
python manage.py test temperature
we’ve successfully implemented Celcius-to-Fahrenheit conversion unit test and source code to pass the unit test.
Conclusion
We created a small Django application that converts temperature measurement using TDD. We went through the TDD cycle of test definition, test failure, and implementation/refactoring to make the test pass. As we did so, we discovered that passing a test essentially ensured that the defined criteria was met.
We’ve managed to achieve and maintain a good level of test coverage, and we’ve created tests to serve as documentation for anyone unfamiliar with our work.
As previously said, the temperature conversion tool allows for a great deal of personal experimentation. For example, what about you start by doing Fahrenheit-to-Celcius conversion using TDD and let us know how that works out for you.