I encourage developers to see the value of unit testing; I urge them to get into the habit of writing structured tests alongside their code.
I was reading about Unit Testing and found a blog entry in CodingHorror called I Pity The Fool Who Doesn’t Write Unit Tests, and guess what, he’s right.
Sadly, I’ve encountered a lot of people who doesn’t write tests for their code, and have a CI System (Travis, Jenkins, Gitlab, etc.) only to test the syntax of the code with flake8 or pycodestyle, or the result of calling the software without returning an exception… this is wrong, you’re not testing anything there.
You should be able to test your code to ensure that you’re getting the expected output and then have the confidence to refactor or write new functions without the fear of breaking anything.
There is value in testing, and I’m not talking about religiously test first code later, for me that’s a personal matter, all that I’m saying is that your code won’t have the quality it needs without testing. So stop neglecting Unit Testing and I invite you to read the CodingHorror blog post.
Let’s jump right into it with a primer for python.
Honestly, you should write a failing test first, then write just the necessary code to make it work, and lastly refactor, from now on just rinse and repeat. But as we’re still learning how to code I’ll write the code first and let’s test it later.
We’re going to write a module called
say_hi.pi that has a function called
salute(name) which takes a
name as a single argument and returns
Hello, <name>!. Here’s our code for
Now let’s write a test called
test_say_hi.py for this module to ensure that our code always return the desired string:
Seems a bit long, huh? We’ll break it later, for now let’s see if our code works:
$ python test_say_hi.py
Aaand guess what?:
It works correctly, so what is happening in that test? Let’s break it down.
First we import the unittest module that will let us write tests for our code:
Now we import the function
salutefrom the python file
say_hi.pythat we just wrote.
from say_hi import salute
We create a new class that inherits from
unittest.TestCase, we’re are making a new test case class that will hold our methods to test our
"""Class for testing say_hi.py"""
Now we define our first class method, this method will test our function
salute, and this is the important part, what are we doing with
self.assertEqual? We are making a comparison here, we are asking our test: The function
salute('Anne')should return exactly:
Hello, Anne!, if it’s not the same, then complain!
"""Test salute() function."""
self.assertEqual(salute('Anne'), 'Hello, Anne!')
Lastly this line here is in charge of executing or Unit Tests if it’s called directly as a standalone program.
if __name__ == '__main__':
Now that we have the hang of it, let’s create our own class, it shouldn’t be hard at all.
Let’s create a
Raccoon class with a name (because, why not?) and a
rabid status of
False… because we don’t want a rabid raccoon.
Tha only thing that is going to change is that we are making things the “right way” now. We’re making a Test first, then we write code, and finally we refactor, so let’s dive directly into the unit test.
Now let’s execute our test and let’s see how our tests guide us to write our code:
$ python test_raccoon.py
Our test complains that there’s no such module called
Raccoon, of course there isn’t one because we haven’t created one, so let’s do it:
Now, we execute our test again:
$ python test_raccoon.py
And we find out that it’s all alright, now it’s time to refactor, as we haven’t written almost anything, we should add at least documentation to our class without the fear of breaking anything, unit tests got our backs.
"""Module holding Raccoon class."""
We added simple docstrings to our module, let’s see if we didn’t break anything:
$ python test_raccoon.py
Our test could’ve been better and we need to refactor it, because there are minor details that we should implement, let’s introduce the setUp method.
First of all, if our test is going to use the name
Helga multiple times, then we should define a setUp method so we can define our name only one time to avoid repetition, we do this inside our Test Case class
TestRabidRaccoon. Also we’re changing
assertEqual for a more appropriate a shorter way to check for
False which is
It runs as expected. There are other assertion methods that you can use to test your code, here’s a short list:
|assertEqual(A, B)||Check if A is equal to B|
|assertNotEqual(A, B)||Check if A is not equal to B|
|assertTrue(A)||Check if A is returns True|
|assertFalse(A)||Check if A returns False|
|assertIn(item, list)||Check if item is in list|
|assertNotIn(item, list)||Check if item is not in list|
This is enough to get you started, there’s a lot of value in testing, and you should do it, you’ll become a better developer and you’ll also adopt good practices, if you’re barely starting coding then you will be able to use your test as a guidance because you will be forced to think what you want your code to do first before actually code it.
If you are an experienced developer then you will catch bugs easier, you’ll have confidence when you’re refactoring your code, things are less likely to break, and you will be able to implement new features exactly as you want them.
So, code first and test later, or test first and code later, that’s OK for me, as long as you are testing it.