Python进阶教程:单元测试与代码质量

目录

Python进阶教程:单元测试与代码质量

本文是 Python 入门教程系列 的第 14 篇(扩展篇)。上一篇讲解了装饰器与生成器,本篇介绍如何用单元测试保障代码质量。

一、为什么需要测试

随着代码规模增长,手动验证越来越不可靠。自动化测试能:

  • 快速回归:改动代码后立即发现是否破坏原有功能
  • 驱动设计:写测试时倒逼代码结构清晰
  • 保障重构:放心地优化代码而不怕改坏

二、unittest 基础

unittest 是 Python 内置测试框架:

python 复制代码
import unittest

def add(a, b):
    return a + b

def divide(a, b):
    if b == 0:
        raise ValueError("除数不能为零")
    return a / b

class TestMath(unittest.TestCase):
    def test_add(self):
        self.assertEqual(add(1, 2), 3)
        self.assertEqual(add(-1, 1), 0)

    def test_divide(self):
        self.assertEqual(divide(10, 2), 5)
        with self.assertRaises(ValueError):
            divide(10, 0)

if __name__ == "__main__":
    unittest.main()

运行:python -m unittest test_math.py

三、setUp 与 tearDown

python 复制代码
import unittest

class TestDatabase(unittest.TestCase):
    def setUp(self):
        """每个测试前执行"""
        self.data = {"name": "Alice", "age": 20}

    def tearDown(self):
        """每个测试后执行"""
        self.data.clear()

    def test_data(self):
        self.assertEqual(self.data["name"], "Alice")

    @classmethod
    def setUpClass(cls):
        """整个测试类执行前运行一次"""
        print("开始测试")

    @classmethod
    def tearDownClass(cls):
        """整个测试类执行后运行一次"""
        print("测试结束")

四、pytest:更简洁的框架

pytest 语法更简洁,是社区主流(pip install pytest):

python 复制代码
# test_calculator.py
import pytest

def add(a, b):
    return a + b

def test_add_positive():
    assert add(1, 2) == 3

def test_add_negative():
    assert add(-1, -2) == -3

# 参数化测试
@pytest.mark.parametrize("a,b,expected", [
    (1, 2, 3),
    (0, 0, 0),
    (-5, 5, 0),
])
def test_add_param(a, b, expected):
    assert add(a, b) == expected

# 异常断言
def test_add_raises():
    with pytest.raises(TypeError):
        add("1", 2)

运行:pytest test_calculator.py -v

五、Mock:模拟外部依赖

测试中经常需要模拟网络、数据库等外部依赖:

python 复制代码
from unittest.mock import Mock, patch

def get_user_data(api):
    """从 API 获取用户数据(依赖外部服务)"""
    resp = api.get("/users/1")
    return resp.json()["name"]

def test_get_user_data():
    # 创建一个 Mock API
    mock_api = Mock()
    mock_api.get.return_value.json.return_value = {"name": "Alice"}

    result = get_user_data(mock_api)
    assert result == "Alice"
    mock_api.get.assert_called_with("/users/1")

六、代码质量工具

6.1 代码风格检查

bash 复制代码
# 安装
pip install flake8 black mypy

# 检查代码风格
flake8 my_module.py

# 自动格式化
black my_module.py

# 类型检查
mypy my_module.py

6.2 覆盖率统计

bash 复制代码
# 安装
pip install coverage

# 统计测试覆盖率
coverage run -m pytest
coverage report  # 查看报告
coverage html    # 生成 HTML 报告

七、实战:为工具类编写测试

python 复制代码
# 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("不能除以零")
        return a / b
python 复制代码
# test_calculator.py
import pytest
from calculator import Calculator

@pytest.fixture
def calc():
    """测试夹具:为每个测试提供实例"""
    return Calculator()

def test_add(calc):
    assert calc.add(2, 3) == 5

def test_subtract(calc):
    assert calc.subtract(10, 4) == 6

def test_divide(calc):
    assert calc.divide(8, 2) == 4

def test_divide_by_zero(calc):
    with pytest.raises(ValueError):
        calc.divide(1, 0)

总结

本篇介绍了 unittest 与 pytest 两大测试框架、Mock 模拟外部依赖、以及 flake8/black/mypy/coverage 等代码质量工具,并为计算器类编写了完整测试。养成写测试的习惯,是成为专业开发者的重要一步。

相关推荐
H.莓飛19 小时前
【数据结构】排序_OJ题(一):计数、桶与排序后的处理
java·开发语言·数据结构
wangchunyu11420 小时前
JAVA AQS与Lock实现原理(含CAS)
java·开发语言·word
爱喝水的鱼丶21 小时前
SAP-ABAP:ECC→S/4HANA ABAP 迁移升级指南——程序改造、语法兼容与性能优化 导语
运维·开发语言·性能优化·sap·abap·经验交流·开发交流
小灰灰搞电子21 小时前
Rust+Slint 实现FTP客户端调试助手源码分享
开发语言·后端·rust
外收内放21 小时前
面向对象高级(实战案例)
开发语言·python·学习
专业程序开发源1 天前
springboot欧缇蔓月子中心管理系统82697-计算机课程设计、毕业设计
java·spring boot·后端·python·spring·django·课程设计
FPGA小迷弟1 天前
用 Claude Code 重构遗留系统:从评估到落地的完整实践指南
c++·python·ai·plotly·django·ai编程·claude
卷无止境1 天前
面向arm64桌面客户端开发全景:语言、框架与生态
后端·python
fanruitian1 天前
python else用法
开发语言·python
FRing031 天前
JavaScript入门到精通二十六(变量提升、函数剩余参数、展开运算符、ES6箭头函数)
开发语言·前端·javascript·es6·箭头函数