Ease your way into automated testing in Django.
Tags: django, testing, python, webdev
Published: 2023-01-12 13:00:16

###  Significance of software testing


> Automated testing is an extremely useful bug-killing tool for the modern web developer. ~ [Django Docs](https://docs.djangoproject.com/en/4.1/topics/testing/)

Without automated testing, Software developers would neither have a way to affirm the quality of their code, nor would there be a way to assure that the code does the job it's written to do, until it get deployed and becomes available to users that's when they would have to wait for users feedback.

Writing Tests for any project has become the norm and industrial standard to a point where a programmer can not be taken serious until he writes full functional and unit test for his project and have them go green.

> Automated testing is a process that validates if software is functioning appropriately and meeting requirements before it is released into production. This software testing method uses scripted sequences that are executed by testing tools.

Also check this short article on how to: [Protect Your Sensitive Data: A Guide to .env Files in Django](https://dev.to/defidelity/protect-your-sensitive-data-a-guide-to-env-files-in-django-499e)

### Approach to automated testing

This days, there are many approach to testing a software application and the rise in demand of Test first approach amongst programmers is noticeable, you must have heard about "Test Driven Development (TDD)" if at all you belong to any developer community, in which case test is written first before code implementation, and it is written because the programmer wants it to fail, after which he write codes that would make the tests go green (i.e. passed), the code is written to satisfy the test which is basically the desired output.

The main and most common approach to programming is behavior-driven development (BDD) in which case you develop to satisfy a development plan after which you test to assure quality as opposed to TDD where you develop to satisfy test, then optimize.

Either way, testing a software project is not a joke and must be taken as an important aspect if not the most important aspect of the project, no matter the level of experience the programmer has.

### Testing environment

> Testing a web application is a complex task, because a web application is made of several layers of logic – from HTTP-level request handling, to form validation and processing, to template rendering. ~ [Django Docs](https://docs.djangoproject.com/en/4.1/topics/testing/)

Proper testing environment set-up is a tedious work because it often require going back and forth between documentations and terminal and having allot of config files to set up so as to assert smooth testing experience once development starts.

You need to see this article on [Production ready settings file: Simplest way to get it done](https://dev.to/defidelity/production-ready-settings-file-simplest-way-to-get-it-done-509j)

### Testing in Django

Django as a battery included framework ship all app generated through the management command `python manage.py startapp` for windows and `python3 manage.py startapp` for Mac or Linux with inbuilt test suite configured in a python file named `test.py` where the `TestCase` a class from the test module has already been imported at the top of the file.

But the growth of our project would render the test file irrelevant due to the fact that several layer of the app needs require testing and keeping all this in a file wouldn't make any sense, it would rather reduce the readability of the code and end up ruining things when change is required instead of making things better.

### Steps to set up a proper testing environment in django

In order to have a proper testing environment that requires a one time configuration and would suffix for any project size, we would need to employ some python third party frameworks to help ship our tools faster.
But as project application grows, tests would become more difficult to manage or work with if they’re all saved in a single test file, and also. There are some limitations with Django-inbuilt test suit which can all be handled by python testing library (Pytest).

In this article, we’ll be learning how to efficiently configure pytest into Django and make them sync with each other and blend well. This would breath ease into your journey of unit testing, Functional testing and System testing.

### Steps

- Delete the Django follow-come test-file and creation of a tests folder.

This step is pretty straight forward, we want to go into our app folder, the same folder that hosts the Models, Views and Apps file and delete `tests.py` file. 
After deleting the file, create a new folder and name it `tests`, then inside the tests folder, create a new file named `__init__.py` this is because without initializing it as a module, python wouldn't recognize it as one.

- Pytest Installation and Setup

Now, we install our testing library and configure it to work extremely well with our Django project.

1. Install `pytest-django` via pip

Go to your browser and search for `pytest-django` click on the [link](https://pytest-django.readthedocs.io/en/latest/) that leads to their documentation and copy the pip command to install the package, which is just `pip install pytest-django`, paste this command in your terminal or CMD if you're on windows, then click enter to run the command.

Please note that Pytest is a dependency for `pytest-django`, so it would install Pytest and other Pytest's dependencies alongside it, `pytest-django` just provides an extremely easy way for us to use the Pytest package in our Django environment.
To be sure that the package is successfully installed, run `pytest` in the terminal or CMD and it should return some commands that ends with `===========no tests ran in 0.00s===========`, if the case is different for you, then you would need to reinstall the `pytest-django` library.

2. Creation and setup of pytest.ini file.

In the project folder, the same level with `manage.py file`, create a new file named `pytest.ini`, this is Pytest initiation file that would be run first anytime you run Pytest.
Inside this file we want to initiate Pytest, provide route to our settings module and define the orientation of all tests file, i.e. the type of files pytest should crawl for testing. 
Paste this block into your `pytest.ini` file.

```
# project_name/pytest.ini
[pytest]
DJANGO_SETTINGS_MODULE = project_name.settings
python_files = test_*.py
```

Run `pytest` in the terminal or CMD again and it should return the same log as before but with very slight delay in time, which shows that pytest is trying to initiate itself with our `.ini` file.

- Run an example test.

Now, we can go back into our test folder and create an example test to be sure our pytest is well configured.
Inside the `tests` directory, create a new file named `test_example.py` and paste the dummy code block below in it.

```
# app_name/tests/test_example.py
def test_dummy_example():
    assert 2 == 2
```

Of course this is expected to return True, but it's called dummy-test because we want to use it to test-run our project and be sure that all is well.
If you run `pytest` in the terminal or CMD now, it should return a log that that specify the test folder with the percentage of it's tests that passed and the log should end with `============= 1 passed in 0.01s ============`.

Also note that if we're to replace the code block by the one below, the test would fail and pytest does a really good job by letting you know where exactly something went wrong so that you may fix it for ease.

```
# app_name/tests/test_example.py
def test_dummy_example():
    assert 2 == 1
```

This is the end to this extremely simple guide to testing, I hope this helps and you now understand the reason why you must write tests for your projects even if it's just some dead simple unit test.
Every programmer should get used and comfortable to testing and it's environment and this would give you confidence on the code you wrote.

Do you also say "Praise be to God" whenever your tests goes green?