Last Updated: January 3, 2026
Testing is an essential part of software development. It ensures that your code behaves as expected and helps catch bugs before they reach users. But testing isn't just a box to check off; it's a mindset that can lead to better design and more maintainable code.
Let's dive into the basics of testing in Python, laying the foundation for the more advanced topics to come.
At its core, testing is the process of executing a program with the intent of finding errors. Think of it as a safety net that catches potential issues before they become headaches later on. When you write tests, you define what "correct" behavior looks like, enabling you to verify that your code meets those expectations.
Before we dive deeper, let’s briefly touch on a few common types of testing:
In this chapter, we will primarily focus on unit testing, as it serves as the foundation for other testing types.
To get started, let’s write a simple function and then create a test for it. Consider a function that adds two numbers:
Now, let’s write a test for this function. A straightforward way to write tests in Python is to use the unittest module.
unittest.TestCase. This gives us access to useful assertion methods.assertEqual method checks if the first argument equals the second. If they don’t match, the test fails.This basic structure will be the foundation for all your tests moving forward.
Assertions are the backbone of your tests. They verify that your code produces the expected results. Let’s explore some common assertions provided by unittest.
assertEqual(a, b): Checks if a is equal to b.assertNotEqual(a, b): Verifies that a is not equal to b.assertTrue(x): Checks if x is True.assertFalse(x): Checks if x is False.assertIsNone(x): Verifies that x is None.assertIsNotNone(x): Verifies that x is not None.Let’s add more assertions to our add function test:
Assertions are where the magic happens. They not only validate the output but also help clarify what your code is supposed to do. As you write more tests, your understanding of the code will deepen.
As your project grows, you will accumulate many tests. Keeping them organized is key to maintainability. Here are some strategies:
tests.test_math.py for testing math.py.You can group related tests into classes or modules. For example, if you have multiple functions for mathematical operations, group their tests together:
Organized tests make it easier to locate and manage them, especially in larger projects.
When writing tests, it’s crucial to consider edge cases. These are situations that may not be common but can lead to unexpected behavior. Let’s look at some common edge cases to consider for our add function.
None or empty?You can write tests that handle these edge cases like this:
Ignoring edge cases can lead to bugs that are hard to track down. By considering them, you can make your code more robust and reliable.
Now that we have our tests written, how do we run them? You might already be familiar with manually running your test files, but here are some additional tools and methods that can streamline the process.
You can run all the tests in a directory by using:
This command looks for files that match the pattern test*.py and runs the tests within those files. It’s a handy way to execute your entire test suite with a single command.
Integrating testing into your development workflow is crucial for maintaining code quality. Tools like Travis CI, GitHub Actions, and CircleCI can automatically run your tests whenever you push changes to your repository.
Now that you understand the basics of testing, you are ready to explore the unittest Module. In the next chapter, we will dive deeper into this module, learning how to leverage its features for more effective unit testing, including advanced assertion methods and test discovery.