一、unittest框架介绍
unittest是Python内置的标准测试框架,最初受JUnit启发设计。它提供了一套完整的测试解决方案,包括:
- 测试用例(TestCase)的创建与组织
- 测试装置(setUp/tearDown)管理
- 丰富的断言方法
- 测试套件(TestSuite)组装
- 测试运行器(TestRunner)执行
- 测试结果收集与报告
使用unittest可以确保代码质量,提高可维护性,减少回归错误。
二、基本测试用例编写
测试用例是unittest的核心组件,每个测试用例都是unittest.TestCase的子类:
import unittest
# 创建测试类
class MathOperationsTest(unittest.TestCase):
# 测试方法必须以test_开头
def test_addition(self):
result = 10 + 5
self.assertEqual(result, 15) # 断言
def test_subtraction(self):
result = 10 - 5
self.assertEqual(result, 5)
命名规范:测试类名称以Test结尾,测试方法以test_开头,这样unittest才能自动识别它们。
三、常用断言方法
unittest提供多种断言方法验证测试结果:
基本断言
assertEqual(a, b)- 检查a == bassertNotEqual(a, b)- 检查a != bassertTrue(x)- 检查x为TrueassertFalse(x)- 检查x为False
容器断言
assertIn(a, b)- 检查a在b中assertNotIn(a, b)- 检查a不在b中assertIsNone(x)- 检查x为NoneassertIsNotNone(x)- 检查x不为None
类型与异常
assertIsInstance(a, b)- 检查a是b类型assertRaises(Exc, func)- 检查函数引发异常assertGreater(a, b)- 检查a > bassertLess(a, b)- 检查a < b
四、测试装置(setUp与tearDown)
测试装置用于准备测试环境和清理资源:
class DatabaseTest(unittest.TestCase):
def setUp(self):
# 每个测试方法前执行
self.db = connect_to_test_db()
self.db.create_table('users')
def tearDown(self):
# 每个测试方法后执行
self.db.drop_table('users')
self.db.close()
def test_user_insert(self):
self.db.insert_user('Alice')
user = self.db.get_user('Alice')
self.assertIsNotNone(user)
def test_user_delete(self):
self.db.insert_user('Bob')
self.db.delete_user('Bob')
user = self.db.get_user('Bob')
self.assertIsNone(user)
对于类级别的装置,使用setUpClass和tearDownClass方法。
五、测试套件(TestSuite)
TestSuite用于组织多个测试用例:
# 创建测试套件
suite = unittest.TestSuite()
# 添加单个测试
suite.addTest(MathOperationsTest('test_addition'))
# 添加整个测试类
suite.addTest(unittest.makeSuite(DatabaseTest))
# 从模块加载测试
from myapp.tests import module_tests
suite.addTests(unittest.TestLoader().loadTestsFromModule(module_tests))
# 运行测试套件
runner = unittest.TextTestRunner()
runner.run(suite)
六、跳过测试与预期失败
unittest提供装饰器控制测试执行:
class AdvancedTests(unittest.TestCase):
@unittest.skip("跳过此测试,功能待实现")
def test_future_feature(self):
# 未实现的测试
pass
@unittest.skipIf(sys.version_info < (3, 8), "需要Python 3.8+")
def test_python38_feature(self):
# 使用Python 3.8特性的测试
pass
@unittest.expectedFailure
def test_broken_feature(self):
# 已知有问题的测试
self.assertEqual(1, 2) # 预期会失败
七、测试发现与执行
unittest支持自动发现测试:
命令行执行
# 自动发现并运行所有测试 python -m unittest discover # 指定测试目录 python -m unittest discover -s tests # 运行单个测试模块 python -m unittest test_module # 运行单个测试类 python -m unittest test_module.TestClass # 运行单个测试方法 python -m unittest test_module.TestClass.test_method
代码中执行
if __name__ == '__main__':
# 运行当前模块的所有测试
unittest.main()
# 运行指定测试
unittest.main(argv=['ignored', '-v', 'MathOperationsTest'])
# 使用HTMLTestRunner生成报告
with open('test_report.html', 'w') as f:
runner = HTMLTestRunner.HTMLTestRunner(
stream=f,
title='测试报告',
description='单元测试结果'
)
runner.run(suite)
八、完整项目示例
一个简单的计算器测试示例:
# calculator.py
class Calculator:
def add(self, a, b):
return a + b
def subtract(self, a, b):
return a - b
def multiply(self, a, b):
return a * b
def divide(self, a, b):
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
# test_calculator.py
import unittest
from calculator import Calculator
class CalculatorTest(unittest.TestCase):
def setUp(self):
self.calc = Calculator()
def test_add(self):
self.assertEqual(self.calc.add(2, 3), 5)
self.assertEqual(self.calc.add(-1, 1), 0)
def test_subtract(self):
self.assertEqual(self.calc.subtract(5, 3), 2)
def test_multiply(self):
self.assertEqual(self.calc.multiply(3, 4), 12)
def test_divide(self):
self.assertEqual(self.calc.divide(10, 2), 5)
with self.assertRaises(ValueError):
self.calc.divide(10, 0)
if __name__ == '__main__':
unittest.main()
运行测试:
$ python test_calculator.py .... ---------------------------------------------------------------------- Ran 4 tests in 0.001s OK
掌握单元测试,提升代码质量
unittest是Python开发者必备的工具,它能帮助您:
✓
减少错误
✓
提高可靠性
✓
简化重构
开始为您的项目编写测试,享受稳定可靠的代码!
发表评论