Testing your code the easy way
Python testing is critical for software quality. Without tests, your code is prone to bugs and errors that can impact user experience.
That’s why it’s important to know how to write tests in Python. In this article, we’ll walk through the basics of Python testing and talk about some of the most popular Python testing tools.
What is Python testing?
Python testing is the process of testing Python code to verify that it works as expected. Python tests can be written using a number of different tools and frameworks, such as unittest, pytest, and nose.
Python tests typically consist of a test suite, which is a collection of test cases. A test case is a single unit of testing, which tests a specific functionality in your Python code.
For example, let’s say you have a function that calculates the average of a list of numbers. A test case for this function might verify that the function returns the correct answer for a specific list of numbers.
Why is Python testing important?
Python testing is important because it helps you catch bugs and errors in your code before your users do. By writing and running tests, you can ensure that your code is working as expected and that any changes you make don’t break existing functionality.
In addition, Python tests can serve as documentation for your code. When you write a test, you’re essentially specifying how your code should work. This can be helpful for other developers who are working on your code or for future you who might need to make changes to your code.
How to write Python tests
Now that we’ve talked about what Python testing is and why it’s important, let’s talk about how to actually write Python tests.
As we mentioned earlier, there are a number of different tools and frameworks you can use for Python testing. In this section, we’ll focus on the unittest framework, which is included with the Python standard library.
If you’re not familiar with the concept of object-oriented programming, don’t worry - we’ll keep things simple. You can think of a class as a template for creating objects. An object is a specific instance of a class.
For example, let’s say you have a class called Dog. This class might have attributes like name, age, and breed. You can create an individual dog object by specifying values for these attributes.
In Python, a class is defined using the class keyword, like this:
class Dog:
def __init__(self, name, age, breed):
self.name = name
self.age = age
self.breed = breed
def bark(self):
print('Woof!')
In this example, the Dog class has three attributes: name, age, and breed. The __init__
method is a special method that is called when an object is created. This method is used to initialize the object’s attributes.
The Dog class also has a bark method, which is a function that defines what happens when the dog barks. In this case, the dog will print the string 'Woof!' when it barks.
We can create a Dog object by calling the Dog class, like this:
my_dog = Dog('Rex', 3, 'Labrador')
In this example, we’re creating a Dog object with the name 'Rex', the age 3, and the breed 'Labrador'.
We can access the attributes of our Dog object using dot notation, like this:
my_dog.name
This will return the value 'Rex'.
We can also call the methods of our Dog object, like this:
my_dog.bark()
This will cause the dog to bark and print the string 'Woof!'
Now that we’ve covered the basics of object-oriented programming in Python, let’s talk about how to write tests using the unittest framework.
The unittest framework is based on the concept of test fixtures. A test fixture is a collection of objects that are used as the environment for a test.
For example, let’s say we have a class that represents a bank account. This class might have methods for depositing and withdrawing money from the account.
We can write a test fixture for this class by creating a class that inherits from the unittest.TestCase class, like this:
import unittest
class TestBankAccount(unittest.TestCase):
def setUp(self):
self.account = BankAccount('John Doe', 100)
def test_deposit(self):
self.account.deposit(50)
self.assertEqual(self.account.balance, 150)
def test_withdraw(self):
self.account.withdraw(10)
self.assertEqual(self.account.balance, 90)
if __name__ == '__main__':
unittest.main()
In this example, we’ve created a TestBankAccount class that inherits from unittest.TestCase. This class has two methods: setUp and test_deposit.
The setUp method is a special method that is called before each test is run. This method is used to set up the environment for the test. In this case, we’re using it to create a BankAccount object.
The test_deposit
method is a test case that tests the deposit method of the BankAccount class. This method first calls the deposit method and then uses the assertEqual method to verify that the account’s balance is correct.
We can run this test suite by running the Python script, like this:
python test_bank_account.py
This will run the setUp method and then the test_deposit method. If the test passes, we should see the following output:
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
If the test fails, we should see an error message that tells us what went wrong.
The unittest framework also has a number of other assert methods that we can use, such as assertTrue and assertFalse.
We can also write test cases for the withdraw method by adding another test case to our TestBankAccount class, like this:
def test_withdraw(self):
self.account.withdraw(10)
self.assertEqual(self.account.balance, 90)
If we run our test suite again, we should see that two tests are now being run:
.
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
You can learn more about the unittest framework in the Python documentation.
There are also a number of other Python testing tools and frameworks that you can explore, such as pytest and nose.
Conclusion
Python testing is important for software quality. In this article, we’ve covered the basics of Python testing and talked about some of the most popular Python testing tools.
Subscribe to my newsletter
Read articles from Jared Atandi directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Jared Atandi
Jared Atandi
I am a developer with a deep love for tweaking things.