Why do we need unit test? And how to write it in Python?

A good program must be correct. Try to imagine getting negative salary because of a bug. To verify how the program work, you must test it. But testing by hand is slow and unreliable. By the time you are testing a program, your competitor might already release the third version of their program! In this post, I will mention one of the tests called unit tests.

What is a unit test?

Unit test is a test for a small part of program. For example, testing abs function to always output absolute value is a unit test. Unit test is testing in smallest part of a program.

Let's write a unit test

In this post, we will write a unit test for same_line function. same_line checks if the given three points are on the same line.

First, let's write a function. Normally in test-driven development, programmers usually write tests first. But doing that will make IDE or text editor screams in undefined function. Let's write a stub function in sameline.py.

"""Check three points are on the same line or not"""
from typing import Tuple

def same_line(a: Tuple[int, int], b: Tuple[int, int], c: Tuple[int, int]) -> bool:
    """Return True if point a, b, and c are on the same line."""
    # It is a stub.
    return True

I use typing module to make type clear. You don't need to do that, but it is better to have type.

Then we write test cases. In Python, we can use unittest module to write unit test in sameline_test.py.

"""Tests for same line function"""
import unittest

from sameline import same_line

class SameLineTest(unittest.TestCase):
    """Tests for same line function"""

    def test_same_x(self):
        """If x does not change, they are on the same line."""
        self.assertTrue(same_line((1, 2), (1, 3), (1, 4)))
        self.assertTrue(same_line((1, -2), (1, -3), (1, -4)))
        self.assertTrue(same_line((10, 1), (10, 2), (10, -999)))

    def test_same_y(self):
        """If y does not change, they are on the same line."""
        self.assertTrue(same_line((1, 2), (3, 2), (4, 2)))
        self.assertTrue(same_line((1, 4), (3, 4), (4, 4)))
        self.assertTrue(same_line((1, -1), (3, -1), (4, -1)))

    def test_slope(self):
        """If they share same slope, they are on the same line."""
        self.assertTrue(same_line((1, 2), (2, 3), (3, 4)))
        self.assertTrue(same_line((2, 3), (1, 1), (0, -1)))

You can use python -m unittest sameline_test.py to run the unit test. Let's see the result.

Screen Shot 2564-12-30 at 14.31.53.png

Wait a minute. We haven't written anything yet. This happened because the function always returns True and we didn't test a case where the function should return False. Let's add a test.

    # Put this after the previous code.
    def test_triangle(self):
        """If they can form a triangle, they are not on the same line."""
        self.assertFalse(same_line((0, 1), (1, 0), (0, 0)))
        self.assertFalse(same_line((12, 1), (3, 3), (-1, -99)))

Screen Shot 2564-12-30 at 14.34.36.png

It's much better now. Now we know that this function does not work. If the function works, it should pass all tests now.

Note: The program may still contain some bugs even all test cases passed. You can use code coverage to find some uncovered tests.

I have a challenge for you. Try to write same_line function to check if point a, b, and c are in the same line. Optional challenge is to support 3D coordinate or cover more points. I hope this post will be useful to Python developers.