当前位置:首页 > Python > 正文

Python unittest框架完整使用教程 - 从入门到精通

Python unittest框架完整使用教程

掌握单元测试的核心技能,提升代码质量与可靠性

一、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 == b
  • assertNotEqual(a, b) - 检查a != b
  • assertTrue(x) - 检查x为True
  • assertFalse(x) - 检查x为False

容器断言

  • assertIn(a, b) - 检查a在b中
  • assertNotIn(a, b) - 检查a不在b中
  • assertIsNone(x) - 检查x为None
  • assertIsNotNone(x) - 检查x不为None

类型与异常

  • assertIsInstance(a, b) - 检查a是b类型
  • assertRaises(Exc, func) - 检查函数引发异常
  • assertGreater(a, b) - 检查a > b
  • assertLess(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)

对于类级别的装置,使用setUpClasstearDownClass方法。

五、测试套件(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开发者必备的工具,它能帮助您:

减少错误

提高可靠性

简化重构

开始为您的项目编写测试,享受稳定可靠的代码!

Python unittest教程 | 提供完整的单元测试指南

发表评论