Skip to content

Commit 46b684f

Browse files
[Edit] Python: unittest-module (#6621)
* [Edit] Python (Pillow): pillow * Update pillow.md * [Edit] Python: unittest-module * Update content/python/concepts/unittest-module/unittest-module.md * Update content/python/concepts/unittest-module/unittest-module.md ---------
1 parent 598b956 commit 46b684f

File tree

1 file changed

+148
-24
lines changed

1 file changed

+148
-24
lines changed

content/python/concepts/unittest-module/unittest-module.md

+148-24
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
Title: 'Unittest Module'
3-
Description: 'The unittest module provides features for unit testing Python code.'
3+
Description: 'Python’s unittest module is a built-in testing framework that helps developers create, organize, and run unit tests.'
44
Subjects:
55
- 'Computer Science'
66
- 'Data Science'
@@ -17,13 +17,41 @@ CatalogContent:
1717
- 'paths/computer-science'
1818
---
1919

20-
The **`unittest`** [module](https://www.codecademy.com/resources/docs/python/modules) provides features for [unit testing](https://www.codecademy.com/resources/docs/general/unit-testing) Python code. Similar to unit testing frameworks in other languages ,`unittest` allows for the following features:
21-
22-
- Automation of unit tests.
23-
- Sharing of setup and tear-down code for tests.
24-
- Aggregation of tests into collections.
25-
26-
## Example
20+
Python **`unittest`** [module](https://www.codecademy.com/resources/docs/python/modules) is a built-in testing [framework](https://www.codecademy.com/resources/docs/general/framework) that provides a set of tools for testing code's functionality in a more systematic and automated way. It supports creating and running [unit tests](https://www.codecademy.com/resources/docs/general/unit-testing), helping developers catch bugs early and ensure code reliability. Similar to unit testing frameworks in other languages, `unittest` allows for the following features:
21+
22+
- Automation of test execution
23+
- Setup and teardown functionality for preparing and cleaning up before/after tests
24+
- Grouping of tests into test suites
25+
26+
## Commonly Used `unittest` Methods
27+
28+
This table lists the most frequently used methods in Python’s `unittest` module. These include assertion methods that check specific conditions in tests, as well as setup and teardown methods that manage test environments:
29+
30+
| **Method** | **Description** |
31+
| ---------------------------- | -------------------------------------------------------- |
32+
| `assertEqual(a, b)` | Test passes if `a == b`. |
33+
| `assertNotEqual(a, b)` | Test passes if `a != b`. |
34+
| `assertTrue(x)` | Test passes if `bool(x) is True`. |
35+
| `assertFalse(x)` | Test passes if `bool(x) is False`. |
36+
| `assertIs(a, b)` | Test passes if `a is b` (same object). |
37+
| `assertIsNot(a, b)` | Test passes if `a is not b`. |
38+
| `assertIsNone(x)` | Test passes if `x is None`. |
39+
| `assertIsNotNone(x)` | Test passes if `x is not None`. |
40+
| `assertIn(a, b)` | Test passes if `a in b`. |
41+
| `assertNotIn(a, b)` | Test passes if `a not in b`. |
42+
| `assertIsInstance(a, b)` | Test passes if `a` is an instance of `b`. |
43+
| `assertNotIsInstance(a, b)` | Test passes if `a` is _not_ an instance of `b`. |
44+
| `assertGreater(a, b)` | Test passes if `a > b`. |
45+
| `assertGreaterEqual(a, b)` | Test passes if `a >= b`. |
46+
| `assertLess(a, b)` | Test passes if `a < b`. |
47+
| `assertLessEqual(a, b)` | Test passes if `a <= b`. |
48+
| `assertAlmostEqual(a, b)` | Test passes if `a ≈ b` (to 7 decimal places by default). |
49+
| `assertNotAlmostEqual(a, b)` | Test passes if `a ≠ b` within tolerance. |
50+
| `assertRaises(Exception)` | Checks if the specified exception is raised. |
51+
| `setUp()` | Prepares test environment; runs before each test method. |
52+
| `tearDown()` | Cleans up after each test method is executed. |
53+
54+
## Example 1: Testing a `Rectangle` Class
2755

2856
The following example begins with code for a `Rectangle` [class](https://www.codecademy.com/resources/docs/python/classes) that needs to be tested:
2957

@@ -54,6 +82,8 @@ import unittest
5482
import rectangle as rect
5583

5684
class RectangleTestCase(unittest.TestCase):
85+
def setUp(self):
86+
self.rectangle = rect.Rectangle(5, 10)
5787

5888
def test_area(self):
5989
self.assertEqual(self.rectangle.area(), 50)
@@ -71,25 +101,24 @@ class RectangleTestCase(unittest.TestCase):
71101
with self.assertRaises(TypeError):
72102
a = self.rectangle.perimeter()
73103

74-
def setUp(self):
75-
self.rectangle = rect.Rectangle(5 ,10)
76-
77104
if __name__ == '__main__':
78105
unittest.main()
79106
```
80107

81-
First the `unittest.TestCase` class is subclassed for our test case object. Then tests are defined as methods with names starting with `test`. This naming convention is mandatory as it allows the test runner to find the methods that represent tests.
82-
83-
Tests consist of methods containing calls to one or more `assert` methods of the test case object:
108+
To run the tests, include:
84109

85-
- `.assertEqual()`: Test passes when both arguments are equal.
86-
- `.assertTrue()` : Test passes when argument is `True`.
87-
- `.assertFalse()` : Test passes when argument is `False`.
88-
- `.assertRaises()` : Test passes when the passed exception is raised.
110+
```py
111+
if __name__ == '__main__':
112+
unittest.main()
113+
```
89114

90-
The test case can have `.setUp()` and `.tearDown()` methods defined. The `.setUp()` method is for any initialization needed for the test, and will run before each `test` method is carried out. The `.tearDown()` method is run after each `test` method to do any needed cleanup after each test.
115+
The `unittest.TestCase` class is subclassed to define a test case object. Each test method must start with the word `test` so the test runner can detect and execute it. A breakdown of all the tests will be as follows:
91116

92-
The call to `unittest.main()` runs the tests and provides the test script with a command-line interface.
117+
- `setup()`: Initializes a `Rectangle` object before each test method runs.
118+
- `test_area()`: Verifies that the area calculation is correct (`5 * 10 = 50`).
119+
- `test_area()`: Checks the perimeter (`2 * (5 + 10) = 30`).
120+
- `test_isSquare()`: Asserts that a rectangle with unequal sides is not a square, and that changing width to equal height makes it a square.
121+
- `test_error()`: Ensures a `TypeError` is raised when width is set to a non-numeric value.
93122

94123
Running the above produces the following:
95124

@@ -100,7 +129,7 @@ $ python test.py
100129
Ran 4 tests in 0.001s
101130
```
102131

103-
The output shows a dot printed for each successful test.
132+
Each dot (`.`) represents a passing test.
104133

105134
Using the `-v` option on the command line will produce a more verbose test:
106135

@@ -117,6 +146,101 @@ Ran 4 tests in 0.001s
117146

118147
The output shows the following:
119148

120-
- The method name for each test.
121-
- The test case class the method belongs to.
122-
- A message telling whether or the test was passed.
149+
- Each test method's name
150+
- Its test case class
151+
- A result message indicating whether it passed
152+
153+
## Example 2: Testing a `BankAccount` Class
154+
155+
This example demonstrates how to write unit tests for a basic bank account class, covering deposit, withdrawal, and balance operations.
156+
157+
```py
158+
# bank_account.py
159+
160+
class BankAccount:
161+
def __init__(self, owner, balance=0):
162+
self.owner = owner
163+
self.balance = balance
164+
165+
def deposit(self, amount):
166+
if amount < 0:
167+
raise ValueError("Deposit amount must be positive.")
168+
self.balance += amount
169+
return self.balance
170+
171+
def withdraw(self, amount):
172+
if amount > self.balance:
173+
raise ValueError("Insufficient funds.")
174+
self.balance -= amount
175+
return self.balance
176+
177+
def get_balance(self):
178+
return self.balance
179+
```
180+
181+
Writing the unit tests for this:
182+
183+
```py
184+
# test_bank_account.py
185+
186+
import unittest
187+
from bank_account import BankAccount
188+
189+
class BankAccountTestCase(unittest.TestCase):
190+
191+
def setUp(self):
192+
self.account = BankAccount("Alice", 100)
193+
194+
def test_deposit(self):
195+
self.assertEqual(self.account.deposit(50), 150)
196+
197+
def test_withdraw(self):
198+
self.assertEqual(self.account.withdraw(30), 70)
199+
200+
def test_withdraw_insufficient_funds(self):
201+
with self.assertRaises(ValueError):
202+
self.account.withdraw(200)
203+
204+
def test_deposit_negative_amount(self):
205+
with self.assertRaises(ValueError):
206+
self.account.deposit(-20)
207+
208+
def test_get_balance(self):
209+
self.assertEqual(self.account.get_balance(), 100)
210+
211+
if __name__ == '__main__':
212+
unittest.main()
213+
```
214+
215+
In the test cases:
216+
217+
- `setUp()`: Creates an account with `owner='Alice'` and initial balance of `100`.
218+
- `test_deposit()`: Tests depositing a valid amount (`50`) updates the balance to `150`.
219+
- `test_withdraw()`: Tests withdrawing `30` correctly reduces the balance to `70`.
220+
- `test_withdraw_insufficient_funds()`: Ensures withdrawing more than available (`200`) raises a `ValueError`.
221+
- `test_deposit_negative_amount()`: Ensures depositing a negative amount raises a `ValueError`.
222+
- `test_get_balance()`: Verifies the balance remains unchanged initially (`100`).
223+
224+
## Best Practices for Using `unittest` Module
225+
226+
- Use `setUp()` for repeated setup code instead of duplicating it in each test.
227+
- Name test methods clearly to describe what’s being tested.
228+
- Keep tests isolated—each test should not depend on another.
229+
- Avoid testing multiple concerns in one test method.
230+
- Run tests frequently during development, not just before deployment.
231+
- Use descriptive assertion messages (e.g., `self.assertEqual(a, b, "Area calculation failed")`) for easier debugging.
232+
233+
## Frequently Asked Questions
234+
235+
### 1. Which is better, `pytest` or `unittest`?
236+
237+
`unittest` is built into Python and follows an object-oriented approach. It is ideal for small to medium-sized projects.
238+
`pytest` is a third-party framework that offers more concise syntax, better error messages, and additional plugins, making it a popular choice for larger projects.
239+
240+
### 2. What does `unittest.main()` do?
241+
242+
`unit test.main()` launches the test runner, which automatically discovers and executes all test methods in the file. It also provides a command-line interface to control test behavior (e.g., verbosity).
243+
244+
### 3. What does `if __name__ == '__main__'` mean in Python?
245+
246+
This statement ensures that the code inside runs only when the script is executed directly, not when it’s imported as a module. It's commonly used to run test scripts or demo code.

0 commit comments

Comments
 (0)