单元测试执行失败时,框架会输出一系列精确定位问题的消息。理解这些信息能显著提升调试效率。
假设有一个问候函数定义如下:
# greeter.py
def say_hello(name):
greeting = "Hi, "
return greeting + name.title()
对应的测试用例写为:
# test_greeter.py
import unittest
from greeter import say_hello
class GreetingTests(unittest.TestCase):
def test_greet_single_name(self):
msg = say_hello('alice')
self.assertEqual(msg, 'Hi, Alice')
if __name__ == '__main__':
unittest.main()
此时测试通过。若需求变化,问候语需要同时包含名和姓,我们将函数改为接收两个参数:
# greeter.py(修改后)
def say_hello(first, last):
greeting = "Hi, "
return greeting + first.title() + ' ' + last.title()
重新运行原来的测试,控制台会出现类似以下的输出:
E
======================================================================
ERROR: test_greet_single_name (__main__.GreetingTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_greeter.py", line 7, in test_greet_single_name
msg = say_hello('alice')
TypeError: say_hello() missing 1 required positional argument: 'last'
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (errors=1)
开头的大写
E 表示存在一个错误(Error),而非失败(Fail)。紧接着的错误定位显示了是
GreetingTests.test_greet_single_name 触发了异常。回溯信息明确指出
say_hello('alice') 调用缺少必备的
last 形参。最后
FAILED 提示整个测试执行未成功,因为发生了错误。
根据这些提示,我们能立刻知道需要修复函数,使其兼容单个参数和两个参数两种场景。可以为
last 设置默认值:
# greeter.py(最终版)
def say_hello(first, last=''):
greeting = "Hi, "
if last:
return greeting + first.title() + ' ' + last.title()
else:
return greeting + first.title()
现在函数既可以处理单个名字,也能处理完整的姓名。我们为新增的全名场景补充一个测试方法:
# test_greeter.py(更新后)
import unittest
from greeter import say_hello
class GreetingTests(unittest.TestCase):
def test_greet_single_name(self):
msg = say_hello('alice')
self.assertEqual(msg, 'Hi, Alice')
def test_greet_full_name(self):
msg = say_hello('alice', 'smith')
self.assertEqual(msg, 'Hi, Alice Smith')
if __name__ == '__main__':
unittest.main()
再次运行测试,输出将显示两个测试均通过:
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
通过测试的反馈(两个点表示两个测试通过,最后显示
OK)可以确认新功能没有破坏原有行为,并且新增需求也被正确实现。
最后,
unittest 模块中常用的断言方法可总结如下:
| 方法 | 用途 |
| assertEqual(a, b) | 验证 a == b |
| assertNotEqual(a, b) | 验证 a != b |
| assertTrue(x) | 验证 x 为真 |
| assertFalse(x) | 验证 x 为假 |
| assertIn(item, container) | 验证 item 位于 container 中 |
| assertNotIn(item, container) | 验证 item 不在 container 中 |