一、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开发者必备的工具,它能帮助您:
✓
减少错误
✓
提高可靠性
✓
简化重构
开始为您的项目编写测试,享受稳定可靠的代码!
发表评论