Easy Free Automation Part I: Unit Tests

This post is the beginning of an eight-part series on easy, free ways to automate each area of the Automation Test Wheel.  It’s been my experience that there are a number of barriers to learning test automation.  First, the team you are on might not need certain types of automation.  For example, my team has been solely API-focused, so for the last two years I haven’t had much reason to do UI automation.  Second, your company may already have invested in specific automation tools, so when you want to learn to use a different tool, you need to do it on your own.  Third, there are many tools that have barriers to using them, such as a high cost or a complicated setup.  And finally, there is not always good documentation out there to help people get started.

In this series, I’m hoping to provide simple, free examples that will demonstrate each area of the Automation Test Wheel in practice, which you can use as a jumping-off point in your own automation journey.  We’ll begin with unit tests.

Unit tests are usually written by developers, but it’s a good idea for all software testers to understand what they are and how they work.  Unit tests test just one method or function, and they aim to exercise as many paths of that method or function as possible.  The major benefit of unit tests is that they provide extremely fast, accurate feedback.
I’m going to use Python and Pytest to demonstrate how unit tests work.  I am admittedly not an expert in either, but I managed to put together a little project with just one function.  If you would like to try the code out yourself, I have added it to GitHub here.  (If you have never cloned a Git repository before, you can find some instructions here.)
To run the tests, you will need to have Python installed.  There are some great directions for installing Python here.  Installing Python 3 will most likely install pip, the Python package installer, but if it doesn’t, you can get installation instructions here.  Finally, you’ll need to use pip to install Pytest; there are instructions for that here.  (If all this seems like too much work, you can just read on and look at the examples.)
In the file called _init_.py, I’ve written a simple function called isItADozen that determines whether a number of objects equals a dozen.  Here’s the code:
def isItADozen(input): 
if type(input) != int:
result = “This is not a number”
elif input == 12:
result = “Yup, it’s a dozen!”
elif input < 12 and input > 0:
result = “Nope, you have less than a dozen”
elif input > 12:
result = “You have more than a dozen here”
elif input <=0:
result = “You don’t have any at all!”
return result

The function takes the input and first checks to see if it’s an integer.  If not, it returns the message “This is not a number”.  Then it checks to see whether the number is 12, or is more than 12, or is between 0 and 12, or is less than 0.  Depending on which statement is true, it will return an appropriate message.  
Before we look at the unit tests, let’s think about how we would test this function manually, assuming it had a UI interface.  We’d check to make sure it recognized 12 as a dozen, we’d check to make sure it recognized when a number was more than or less than a dozen, and we’d also try some of the usual QA tricks, like passing in a negative number or “FOO”.  
That’s exactly what we’ll do with our unit tests!  Here is the code in my test.py file:
import unittest

from my_test import isItADozen

class TestDozen(unittest.TestCase):
    def test_a_dozen(self):
        result = isItADozen(12)
        self.assertEqual(result, “Yup, it’s a dozen!”)

    def test_more_than_a_dozen(self):
    result = isItADozen(15)
    self.assertEqual(result, “You have more than a dozen here”)

    def test_less_than_a_dozen(self):
    result = isItADozen(10)
    self.assertEqual(result, “Nope, you have less than a dozen”)

    def test_less_than_zero(self):
    result = isItADozen(-1)
    self.assertEqual(result, “You don’t have any at all!”)

    def test_not_a_number(self):
    result = isItADozen(“FOO”)
    self.assertEqual(result, “This is not a number”)

if __name__ == ‘__main__’:
    unittest.main()

I have five test cases here, aptly named:
test_a_dozen
test_more_than_a_dozen
test_less_than_a_dozen
test_less_than_zero
test_not_a_number

In each test, I call the isItADozen function with the number I want to test with.  Then I assert that the result I got matches the result I was expecting.  

To run my tests, I simply go to the command line, navigate to the unitTestProject folder, and type:

python3 test.py –verbose

(If you don’t know how to use your command line, see my blog post from several years ago.)

You may not need to use the “3” in “python3”- I need to do this because I have Python 2.7.1 installed as well and I want to run on the newer version.  You don’t need to do the “–verbose” command; I like to do this because then it shows me the names of my tests as they pass instead of “…..”, which isn’t much fun.  
Once you have the tests running, try making one fail by changing one of the assert statements like this:
self.assertEqual(result, “This is not the real result message”)
Then see if you can change a test so that you are passing in a different value.  For example, you could pass the number 13 into the “test_more_than_a_dozen” test instead of 15.  
Once you have mastered that, you may want to copy my entire test folder and see if you can write your own simple function and unit tests.  If you are more familiar with another programming language, you can try writing unit tests in that language as well.  
Hopefully this has been an easy way to get you started with writing unit tests!  We’ll continue with the Easy Free Automation series next week.