Unit tests in Python
Tags: python, testing, programming
Published: 2024-01-28 14:14:21

You know how sometimes you write a piece of code and there's a certain way in your head you expect it to behave however, it starts acting like it is possessed? That is exactly why you're reading this.

## What is testing?
When writing software code, it is
 very important it isolate and "modularize" several of its components. Sometimes it really isn't about the syntax or runtime error but really about the semantic errors. You know how they say "the enemy you know is better than the friend you don't know?". This is exactly what this feels like reason for placing measures like writing tests to ensure there are no "enemies" lurking around unnoticed. You also want to be sure that no added code has changed the functionality of pre-existing code. Testing is pretty much assessing the functionality of a program or part of it and essentially looking for errors. 

## What are unit tests?
Let's start by doing a little bit of human biology. Organs with different functionalities make up the human body. Every organ has a specific function and if they don't execute it well, that could be very dangerous for the body. Imagine what will happen if somehow the heart starts pumping water or pumps a very limited amount of blood or starts pumping blood to the wrong direction. That will be chaotic. Picture your software like the human body and the various bits that make it (functions) the organs. Unit tests come in to basically assess the smallest piece of code that can be logically isolated. Essentially testing out a unit of code.

## Python unit tests
We will write a function that does the following:
- accepts a list of integers
- emits an error message if the list is not a multiple of 10 in length
- returns or prints a list of integers based on the input list, but with items at positions which are a multiple of 2 or 3 removed

```python
import logging


logger = logging.getLogger("errorLogger")
logger.setLevel(logging.ERROR)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

def returnIntegers(arr):
    if len(arr) == 0:
        return arr
    if len(arr)%10 != 0:
        logger.error('Error: The length of this array is not a multiple of 10')
    res = []
    for i in range(len(arr)):
        if type(arr[i]) != int:
            return []
        if i%2 != 0 and i % 3 != 0:
            res.append(arr[i])
    return res
```

From the above program, we will have to write tests for 2 things:
- If an error is printed when the length of the input list is not a multiple of 10
- If items at positions which are multiple of 2  or 3 are exclude from the output

## The assert statement
This is a built in function in Python to check if a condition is true or false. If the condition is true, nothing happens. If it's false, an error "Assertion Error" is raised. For our function above, we want to want to assert `returnIntegers([2, 5, 20, 10]) = [5]`

```python
assert returnIntegers([2, 5, 20, 10]) = [5]
```

## The unittest module
This is a module in Python aimed at making working with testcases easier. This module utilizes some object oriented concepts and a testcase is represented by the `TestCase` class. This is because `TestCase`provides serveral of its own assert methods that work just like the assert function above. Some of its assert functions include: `assertEqual`, `assertNotEqual`, `assertTrue`, `assertFalse`, etc. 
Now let us write a test for the function above using the unittest module.

```python
import unittest
import main

class TestFunc(unittest.TestCase):

    def test_returnIntegers(self):
        self.assertEqual(main.returnIntegers([2, 5, 20, 10]), [5])
        self.assertEqual(main.returnIntegers([10, 2, 9, 3, 0, 1, 19, 8, 0, 67, 12, 15]), [2, 1, 8, 15])
        self.assertEqual(main.returnIntegers(["a", "5"]), [])
        

if __name__ == '__main__':
    unittest.main()
```
Below is what you will get from running the above test

```bash
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
```


Read the [documentation](https://docs.python.org/3/library/unittest.html) to learn more about the unittest module, its classes, and the various assertion methods.