Lesson 8 - Testing in Python
8.1. Introduction
Testing is an essential part of the development process. It allows us to verify that our code is working correctly and catch any errors or bugs before releasing our software. In this lesson, we’ll learn how to write tests for our Python code using the unittest
module and explore the assert
statement.
8.2. Why Testing is Important
- Catching errors early: Testing allows us to catch errors and bugs early on, which can save us a lot of time and effort in the long run.
- Improved quality: Writing tests ensures that our code is working correctly and meets our expectations.
- Faster development: With a good set of tests in place, we can make changes to our code more confidently, knowing that our tests will catch any errors.
8.3. The assert
Statement
The assert
statement is a built-in statement in Python used to, as the name says, assert if a given condition is true or not. If the condition is true, nothing happens, but if it’s not true, an error is raised. Although, at first, it may look like the try and except clauses, they are completely different, and assert should not be used for error handling but for debugging and testing reasons.
Here’s an example of how to use the assert
statement:
1
2
3
4
5
6
def add_numbers(a, b):
assert type(a) == int and type(b) == int, "Both inputs must be integers"
return a + b
print(add_numbers(2, 3)) # Output: 5
print(add_numbers("2", 3)) # Raises an AssertionError
In this example, we’re using the assert
statement to check that both inputs to the add_numbers
function are integers. If they are not integers, an AssertionError
is raised.
8.4. Writing Tests
A test is a function that starts with the name test_
followed by a descriptive name. For example:
1
2
3
4
import unittest
def test_addition():
assert 2 + 2 == 4
In this example, we’re testing whether the addition of 2 and 2 equals 4. We use the assert
statement to verify this.
8.5. Running Tests
To run our tests, we’ll use the unittest.main()
function. This function will automatically discover and run all the test functions in our code.
Here’s an example of how to run our tests:
1
2
3
4
5
6
7
import unittest
def test_addition():
assert 2 + 2 == 4
if __name__ == '__main__':
unittest.main()
When we run this code, we’ll see the following output:
1
2
3
4
5
....
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
This means that our test passed successfully!
8.6. Test Cases
A test case is a class that inherits from unittest.TestCase
. We can use test cases to group related tests together.
Here’s an example of how to create a test case:
1
2
3
4
5
6
7
8
import unittest
class TestMathFunctions(unittest.TestCase):
def test_addition(self):
self.assertEqual(2 + 2, 4)
def test_subtraction(self):
self.assertEqual(5 - 3, 2)
In this example, we’ve created a test case called TestMathFunctions
that contains two test methods: test_addition
and test_subtraction
.
8.7. Test Fixtures
A test fixture is a setup and teardown routine that is run before and after each test. We can use fixtures to create a controlled environment for our tests.
Here’s an example of how to create a fixture:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import unittest
from tempfile import TemporaryDirectory
class TestMathFunctions(unittest.TestCase):
def setUp(self):
self.temp_dir = TemporaryDirectory()
def tearDown(self):
self.temp_dir.cleanup()
def test_addition(self):
self.assertEqual(2 + 2, 4)
def test_subtraction(self):
self.assertEqual(5 - 3, 2)
In this example, we’ve created a fixture that creates a temporary directory before each test and cleans it up after each test.
8.8. Best Practices
- Keep your tests simple and focused on one specific behavior.
- Use descriptive names for your tests.
- Use the
assert
statement to verify the expected behavior. - Use fixtures to create a controlled environment for your tests.
- Run your tests regularly to catch any errors or bugs early on.
8.9. Executing Tests
In main project directory, run pytest
from the terminal (check if pytest
is installed with pip install pytest
):
1
pytest
- output:
1
2
3
4
5
6
7
8
platform: Windows-10-10.0.19044-SP0
rootdir: C:\Users\user\Documents\GitHub\python-automation\lesson-08
plugins: python-dotenv
collected 1 item
test_lesson08.py ......
==================== 1 passed in 0.00s ====================
or, if we wish to have more options, run pytest -v
to see the output of the tests.
1
pytest -v
- output: ``` platform: Windows-10-10.0.19044-SP0 rootdir: C:\Users\user\Documents\GitHub\python-automation\lesson-08 plugins: python-dotenv collected 2 items
test_lesson08.py: test_addition PASSED [50%] test_lesson08.py: test_subtraction PASSED [100%] ==================== 2 passed in 0.00s ==================== ```
- or, run
pytest -v -k <test_name>
to run only a specific test.
8.10. Conclusion
You can download the sample codes with testing in Python here: