乐于分享
好东西不私藏

Day 43 | AI生成单元测试:覆盖率从0%到80%

Day 43 | AI生成单元测试:覆盖率从0%到80%

前置说明

本文面向谁?

  • 已经掌握Python基础,想提升代码质量的测试工程师
  • 苦于写单元测试太耗时,想借助AI提效的开发者
  • 对代码覆盖率有要求,但不知道从何入手的同学

本文要解决什么问题?

  • 理解什么是单元测试,为什么它如此重要
  • 掌握用AI工具(Cursor、Claude Code、Copilot)自动生成单元测试的方法
  • 学会从0%覆盖率提升到80%的实战技巧

目录导航

章节
内容
难度
1. 本章学习目标
学完能做什么
2. 概念解释
单元测试是什么+为什么重要
⭐⭐
3. 代码示例
完整可运行的Python代码
⭐⭐⭐
4. 运行效果
展示代码运行后的输出结果
⭐⭐
5. 避坑指南
新手最容易犯的错误
⭐⭐⭐
6. 本章小结 & 下集预告
总结+预告

本章学习目标

学完本章,你将能够:

✅ 理解单元测试的核心概念:知道什么是单元测试,为什么要写,什么时候写

✅ 使用AI工具生成测试代码:掌握Cursor、Claude Code、Copilot生成单元测试的技巧

✅ 计算和提升代码覆盖率:会用coverage.py工具,知道如何从0%提升到80%

✅ 识别测试质量:能判断AI生成的测试是否靠谱,知道如何优化

概念解释

什么是单元测试?

单元测试(Unit Test) 就是对代码中最小的可测试单元(通常是函数或方法)进行验证的测试。

生活化类比:

想象你在组装一台电脑:

  • 单元测试 = 单独测试每个零件(CPU、内存、硬盘)是否正常工作
  • 集成测试 = 把所有零件组装起来,测试整台电脑能不能开机
  • 系统测试 = 装好系统、软件,测试能不能流畅打游戏

为什么单元测试如此重要?

好处
说明
早发现Bug
在开发阶段就发现错误,修复成本最低
重构保障
改代码时不怕破坏原有功能,有测试兜底
文档作用
测试代码就是最好的使用文档
设计反馈
难测试的代码往往设计有问题,倒逼你写出更好的代码

什么是代码覆盖率?

代码覆盖率(Code Coverage) 衡量的是你的测试代码覆盖了多少被测代码。

常见的覆盖率指标:

指标
含义
举例
行覆盖率
测试执行了多少行代码
100行代码,测试跑了80行 = 80%
分支覆盖率
测试覆盖了多少条件分支
if/else两个分支都测到 = 100%
函数覆盖率
测试调用了多少函数
10个函数,测了8个 = 80%

覆盖率不是越高越好!

  • 80% 是一个合理的平衡点
  • 100% 覆盖率不代表没有Bug,只代表代码被执行过
  • 追求100%可能浪费时间在 trivial 代码上

代码示例

示例1:被测代码(一个简单的用户验证模块)

"""
user_validator.py - 用户数据验证模块
"""


import re
from datetime import datetime


classUserValidator:
"""用户数据验证器"""

def__init__(self):
# 定义邮箱正则表达式
        self.email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
# 定义手机号正则(中国大陆)
        self.phone_pattern = r'^1[3-9]\d{9}$'

defvalidate_email(self, email: str) -> bool:
"""
        验证邮箱格式是否正确

        Args:
            email: 待验证的邮箱地址

        Returns:
            bool: 验证通过返回True,否则返回False
        """

# 空值检查
ifnot email ornot isinstance(email, str):
returnFalse

# 长度检查
if len(email) > 254:
returnFalse

# 正则匹配
return bool(re.match(self.email_pattern, email))

defvalidate_phone(self, phone: str) -> bool:
"""
        验证手机号格式是否正确(中国大陆)

        Args:
            phone: 待验证的手机号

        Returns:
            bool: 验证通过返回True,否则返回False
        """

# 空值检查
ifnot phone ornot isinstance(phone, str):
returnFalse

# 正则匹配
return bool(re.match(self.phone_pattern, phone))

defvalidate_age(self, age: int) -> tuple[bool, str]:
"""
        验证年龄是否合法

        Args:
            age: 待验证的年龄

        Returns:
            tuple: (是否合法, 错误信息)
        """

# 类型检查
ifnot isinstance(age, int):
returnFalse"年龄必须是整数"

# 范围检查
if age < 0:
returnFalse"年龄不能为负数"

if age > 150:
returnFalse"年龄不能超过150岁"

returnTrue""

defvalidate_username(self, username: str) -> tuple[bool, str]:
"""
        验证用户名是否合法

        Args:
            username: 待验证的用户名

        Returns:
            tuple: (是否合法, 错误信息)
        """

# 空值检查
ifnot username:
returnFalse"用户名不能为空"

# 类型检查
ifnot isinstance(username, str):
returnFalse"用户名必须是字符串"

# 长度检查
if len(username) < 3:
returnFalse"用户名长度至少3个字符"

if len(username) > 20:
returnFalse"用户名长度不能超过20个字符"

# 格式检查:只能包含字母、数字、下划线
ifnot re.match(r'^[a-zA-Z0-9_]+$', username):
returnFalse"用户名只能包含字母、数字和下划线"

returnTrue""

defvalidate_user(self, user_data: dict) -> dict:
"""
        验证完整的用户数据

        Args:
            user_data: 包含用户信息的字典

        Returns:
            dict: 验证结果,包含is_valid和errors字段
        """

        errors = {}

# 验证邮箱
if'email'in user_data:
ifnot self.validate_email(user_data['email']):
                errors['email'] = "邮箱格式不正确"

# 验证手机号
if'phone'in user_data:
ifnot self.validate_phone(user_data['phone']):
                errors['phone'] = "手机号格式不正确"

# 验证年龄
if'age'in user_data:
            is_valid, error_msg = self.validate_age(user_data['age'])
ifnot is_valid:
                errors['age'] = error_msg

# 验证用户名
if'username'in user_data:
            is_valid, error_msg = self.validate_username(user_data['username'])
ifnot is_valid:
                errors['username'] = error_msg

return {
'is_valid': len(errors) == 0,
'errors': errors
        }


# 简单的使用示例
if __name__ == "__main__":
    validator = UserValidator()

# 测试邮箱验证
    print("邮箱验证测试:")
    print(f"  test@example.com: {validator.validate_email('test@example.com')}")
    print(f"  invalid-email: {validator.validate_email('invalid-email')}")

# 测试用户数据验证
    print("\n用户数据验证测试:")
    user = {
'username''john_doe',
'email''john@example.com',
'phone''13800138000',
'age'25
    }
    result = validator.validate_user(user)
    print(f"  合法用户: {result}")

示例2:AI生成的单元测试代码

"""
test_user_validator.py - 用户验证模块的单元测试
使用pytest框架
"""


import pytest
from user_validator import UserValidator


classTestUserValidator:
"""UserValidator类的测试用例"""

    @pytest.fixture
defvalidator(self):
"""测试夹具:为每个测试方法提供验证器实例"""
return UserValidator()

# ==================== 邮箱验证测试 ====================

deftest_validate_email_valid(self, validator):
"""测试合法的邮箱地址"""
        valid_emails = [
'test@example.com',
'user.name@domain.co.uk',
'user+tag@example.org',
'123@qq.com',
'UPPER@EXAMPLE.COM'
        ]
for email in valid_emails:
assert validator.validate_email(email) isTruef"{email} 应该被识别为合法邮箱"

deftest_validate_email_invalid(self, validator):
"""测试非法的邮箱地址"""
        invalid_emails = [
'',                      # 空字符串
'invalid-email',         # 缺少@符号
'@example.com',          # 缺少用户名
'test@',                 # 缺少域名
'test@.com',             # 域名格式错误
'test@example',          # 缺少顶级域名
'test space@example.com'# 包含空格
'a' * 250 + '@test.com'# 超过长度限制
        ]
for email in invalid_emails:
assert validator.validate_email(email) isFalsef"{email} 应该被识别为非法邮箱"

deftest_validate_email_none_and_empty(self, validator):
"""测试None和空值"""
assert validator.validate_email(NoneisFalse
assert validator.validate_email(''isFalse

deftest_validate_email_wrong_type(self, validator):
"""测试错误的数据类型"""
assert validator.validate_email(123isFalse
assert validator.validate_email([]) isFalse
assert validator.validate_email({'email''test@test.com'}) isFalse

# ==================== 手机号验证测试 ====================

deftest_validate_phone_valid(self, validator):
"""测试合法的手机号"""
        valid_phones = [
'13800138000',
'15912345678',
'18888888888',
'13500000000'
        ]
for phone in valid_phones:
assert validator.validate_phone(phone) isTruef"{phone} 应该被识别为合法手机号"

deftest_validate_phone_invalid(self, validator):
"""测试非法的手机号"""
        invalid_phones = [
'',               # 空字符串
'12345678901',    # 不是1开头
'1380013800',     # 少一位
'138001380000',   # 多一位
'1380013800a',    # 包含字母
'138-0013-8000'# 包含分隔符
        ]
for phone in invalid_phones:
assert validator.validate_phone(phone) isFalsef"{phone} 应该被识别为非法手机号"

# ==================== 年龄验证测试 ====================

deftest_validate_age_valid(self, validator):
"""测试合法的年龄"""
        valid_ages = [011825100150]
for age in valid_ages:
            is_valid, error = validator.validate_age(age)
assert is_valid isTruef"年龄 {age} 应该合法"
assert error == ""f"年龄 {age} 不应该返回错误信息"

deftest_validate_age_invalid_negative(self, validator):
"""测试负数年龄"""
        is_valid, error = validator.validate_age(-1)
assert is_valid isFalse
assert"负数"in error

deftest_validate_age_invalid_too_large(self, validator):
"""测试年龄过大"""
        is_valid, error = validator.validate_age(151)
assert is_valid isFalse
assert"150"in error

deftest_validate_age_invalid_type(self, validator):
"""测试错误的数据类型"""
        is_valid, error = validator.validate_age("25")
assert is_valid isFalse
assert"整数"in error

        is_valid, error = validator.validate_age(25.5)
assert is_valid isFalse

# ==================== 用户名验证测试 ====================

deftest_validate_username_valid(self, validator):
"""测试合法的用户名"""
        valid_names = [
'abc',           # 最小长度
'john_doe',      # 带下划线
'user123',       # 带数字
'a' * 20# 最大长度
        ]
for name in valid_names:
            is_valid, error = validator.validate_username(name)
assert is_valid isTruef"用户名 '{name}' 应该合法"

deftest_validate_username_too_short(self, validator):
"""测试用户名太短"""
        is_valid, error = validator.validate_username('ab')
assert is_valid isFalse
assert"至少3个字符"in error

deftest_validate_username_too_long(self, validator):
"""测试用户名太长"""
        is_valid, error = validator.validate_username('a' * 21)
assert is_valid isFalse
assert"不能超过20个字符"in error

deftest_validate_username_empty(self, validator):
"""测试空用户名"""
        is_valid, error = validator.validate_username('')
assert is_valid isFalse
assert"不能为空"in error

deftest_validate_username_invalid_chars(self, validator):
"""测试包含非法字符的用户名"""
        invalid_names = [
'john-doe',      # 横线
'john.doe',      # 点
'john doe',      # 空格
'john@doe',      # @符号
'john!doe'# 感叹号
        ]
for name in invalid_names:
            is_valid, error = validator.validate_username(name)
assert is_valid isFalsef"用户名 '{name}' 应该不合法"
assert"只能包含"in error

# ==================== 完整用户数据验证测试 ====================

deftest_validate_user_all_valid(self, validator):
"""测试所有字段都合法的用户数据"""
        user_data = {
'username''john_doe',
'email''john@example.com',
'phone''13800138000',
'age'25
        }
        result = validator.validate_user(user_data)
assert result['is_valid'isTrue
assert result['errors'] == {}

deftest_validate_user_multiple_errors(self, validator):
"""测试多个字段同时出错"""
        user_data = {
'username''ab',                    # 太短
'email''invalid-email',            # 格式错误
'phone''123',                      # 格式错误
'age'-5# 负数
        }
        result = validator.validate_user(user_data)
assert result['is_valid'isFalse
assert'username'in result['errors']
assert'email'in result['errors']
assert'phone'in result['errors']
assert'age'in result['errors']

deftest_validate_user_partial_fields(self, validator):
"""测试只提供部分字段"""
        user_data = {
'username''john_doe',
'email''john@example.com'
        }
        result = validator.validate_user(user_data)
assert result['is_valid'isTrue
assert'phone'notin result['errors']
assert'age'notin result['errors']

deftest_validate_user_empty_data(self, validator):
"""测试空数据"""
        result = validator.validate_user({})
assert result['is_valid'isTrue# 没有字段需要验证
assert result['errors'] == {}


# 运行测试的命令:
# pytest test_user_validator.py -v
# pytest test_user_validator.py -v --cov=user_validator --cov-report=html

示例3:使用AI生成测试的Prompt模板

"""
使用AI工具生成单元测试的Prompt模板

在Cursor、Claude Code或Copilot中使用以下Prompt
"""


# ============ Prompt 1:基础版本 ============
"""
请为以下Python代码生成完整的pytest单元测试:

【代码粘贴在这里】

要求:
1. 使用pytest框架
2. 覆盖所有公开方法
3. 包含正常情况和异常情况
4. 使用pytest.fixture提供测试数据
5. 添加中文注释说明每个测试的目的
"""


# ============ Prompt 2:进阶版本 ============
"""
请为以下Python类生成全面的单元测试:

【代码粘贴在这里】

测试要求:
1. 使用pytest框架,类名为TestXXX
2. 每个公开方法至少3个测试用例:
   - 正常输入
   - 边界值
   - 异常情况
3. 使用@pytest.fixture创建测试夹具
4. 使用@pytest.mark.parametrize进行参数化测试(如适用)
5. 测试覆盖率目标:80%以上
6. 添加详细的docstring说明

请生成完整的测试代码,我可以直接复制使用。
"""


# ============ Prompt 3:指定覆盖率目标 ============
"""
请为以下代码生成单元测试,要求达到90%行覆盖率:

【代码粘贴在这里】

请确保:
1. 所有if/else分支都被测试到
2. 所有异常处理路径都被覆盖
3. 边界条件(空值、最大值、最小值)都有测试
4. 生成测试后,告诉我如何运行coverage检查
"""


# ============ Prompt 4:已有测试的优化 ============
"""
请帮我优化以下单元测试代码:

【现有测试代码粘贴在这里】

优化目标:
1. 减少重复代码
2. 使用更合适的pytest特性(fixture、parametrize等)
3. 提高可读性
4. 补充缺失的测试场景

请给出优化后的完整代码,并说明改动原因。
"""

示例4:运行测试和检查覆盖率

"""
run_tests.py - 运行测试并生成覆盖率报告
"""


import subprocess
import sys


defrun_tests():
"""运行单元测试"""
    print("=" * 50)
    print("开始运行单元测试...")
    print("=" * 50)

# 运行pytest,显示详细输出
    result = subprocess.run(
        ['pytest''test_user_validator.py''-v'],
        capture_output=True,
        text=True
    )

    print(result.stdout)
if result.stderr:
        print("错误输出:", result.stderr)

return result.returncode == 0


defrun_tests_with_coverage():
"""运行测试并生成覆盖率报告"""
    print("\n" + "=" * 50)
    print("运行测试并生成覆盖率报告...")
    print("=" * 50)

# 安装pytest-cov(如果还没安装)
# pip install pytest-cov

# 运行测试并生成覆盖率报告
    commands = [
# 终端显示覆盖率摘要
        ['pytest''test_user_validator.py''-v'
'--cov=user_validator''--cov-report=term-missing'],

# 生成HTML报告
        ['pytest''test_user_validator.py''-v'
'--cov=user_validator''--cov-report=html'],

# 生成XML报告(用于CI/CD)
        ['pytest''test_user_validator.py''-v'
'--cov=user_validator''--cov-report=xml']
    ]

for cmd in commands:
        print(f"\n执行: {' '.join(cmd)}")
        result = subprocess.run(cmd, capture_output=True, text=True)
        print(result.stdout)
if result.returncode != 0:
            print(f"命令执行失败: {cmd}")
returnFalse

    print("\n" + "=" * 50)
    print("覆盖率报告已生成!")
    print("- 终端摘要:查看上方输出")
    print("- HTML报告:打开 htmlcov/index.html 查看详细报告")
    print("- XML报告:coverage.xml(用于CI/CD集成)")
    print("=" * 50)

returnTrue


defcheck_coverage_threshold(threshold=80):
"""检查覆盖率是否达到阈值"""
    print(f"\n检查覆盖率是否达到 {threshold}%...")

    result = subprocess.run(
        ['pytest''test_user_validator.py'
'--cov=user_validator''--cov-fail-under', str(threshold)],
        capture_output=True,
        text=True
    )

if result.returncode == 0:
        print(f"✅ 覆盖率已达到 {threshold}% 要求!")
returnTrue
else:
        print(f"❌ 覆盖率未达到 {threshold}% 要求")
        print(result.stdout)
returnFalse


if __name__ == "__main__":
# 步骤1:运行基础测试
ifnot run_tests():
        print("❌ 测试运行失败,请检查代码")
        sys.exit(1)

# 步骤2:生成覆盖率报告
ifnot run_tests_with_coverage():
        print("❌ 覆盖率报告生成失败")
        sys.exit(1)

# 步骤3:检查覆盖率阈值
ifnot check_coverage_threshold(80):
        sys.exit(1)

    print("\n🎉 所有测试通过,覆盖率达标!")

运行效果

1. 运行基础测试

$ pytest test_user_validator.py -v

输出:

============================= test session starts =============================
platform win32 -- Python 3.12.0, pytest-8.0.0, pluggy-1.0.0
rootdir: D:\project
collected 18 items

test_user_validator.py::TestUserValidator::test_validate_email_valid PASSED [  5%]
test_user_validator.py::TestUserValidator::test_validate_email_invalid PASSED [ 11%]
test_user_validator.py::TestUserValidator::test_validate_email_none_and_empty PASSED [ 16%]
test_user_validator.py::TestUserValidator::test_validate_email_wrong_type PASSED [ 22%]
test_user_validator.py::TestUserValidator::test_validate_phone_valid PASSED [ 27%]
test_user_validator.py::TestUserValidator::test_validate_phone_invalid PASSED [ 33%]
test_user_validator.py::TestUserValidator::test_validate_age_valid PASSED [ 38%]
test_user_validator.py::TestUserValidator::test_validate_age_invalid_negative PASSED [ 44%]
test_user_validator.py::TestUserValidator::test_validate_age_invalid_too_large PASSED [ 50%]
test_user_validator.py::TestUserValidator::test_validate_age_invalid_type PASSED [ 55%]
test_user_validator.py::TestUserValidator::test_validate_username_valid PASSED [ 61%]
test_user_validator.py::TestUserValidator::test_validate_username_too_short PASSED [ 66%]
test_user_validator.py::TestUserValidator::test_validate_username_too_long PASSED [ 72%]
test_user_validator.py::TestUserValidator::test_validate_username_empty PASSED [ 77%]
test_user_validator.py::TestUserValidator::test_validate_username_invalid_chars PASSED [ 83%]
test_user_validator.py::TestUserValidator::test_validate_user_all_valid PASSED [ 88%]
test_user_validator.py::TestUserValidator::test_validate_user_multiple_errors PASSED [ 94%]
test_user_validator.py::TestUserValidator::test_validate_user_partial_fields PASSED [100%]

============================== 18 passed in 0.15s ==============================

2. 运行测试并查看覆盖率

$ pytest test_user_validator.py -v --cov=user_validator --cov-report=term-missing

输出:

============================= test session starts =============================
platform win32 -- Python 3.12.0, pytest-8.0.0, pluggy-1.0.0
rootdir: D:\project
plugins: cov-4.1.0
collected 18 items

test_user_validator.py::TestUserValidator::test_validate_email_valid PASSED [  5%]
...
test_user_validator.py::TestUserValidator::test_validate_user_partial_fields PASSED [100%]

---------- coverage: platform win32, python 3.12.0-final-0 -----------
Name                 Stmts   Miss  Cover   Missing
--------------------------------------------------
user_validator.py       65      5    92%   88-92
--------------------------------------------------
TOTAL                   65      5    92%

============================== 18 passed in 0.25s ==============================

覆盖率解读:

  • Stmts:被测代码的总语句数(65行)
  • Miss:未被测试覆盖的语句数(5行)
  • Cover:覆盖率百分比(92%)
  • Missing:具体哪几行没被覆盖(88-92行)

3. 查看HTML覆盖率报告

运行后会生成 htmlcov/index.html,用浏览器打开:

htmlcov/
├── index.html      # 报告首页
├── user_validator.html  # 详细代码覆盖情况
└── style.css       # 样式文件

报告特点:

  • 🟢 绿色:已覆盖的代码
  • 🔴 红色:未覆盖的代码
  • 🟡 黄色:部分覆盖的代码(如条件分支只走了一半)

避坑指南

❌ 错误做法:只测试"正常情况"

# 错误示例:只测试正常输入
deftest_validate_email(validator):
assert validator.validate_email('test@example.com'isTrue

问题:

  • 没有测试非法输入
  • 没有测试边界值(空字符串、超长字符串)
  • 没有测试错误数据类型

✅ 正确做法:全面覆盖各种场景

# 正确示例:测试各种情况
deftest_validate_email_valid(self, validator):
"""测试合法的邮箱地址"""
    valid_emails = [
'test@example.com',
'user.name@domain.co.uk',
'user+tag@example.org'
    ]
for email in valid_emails:
assert validator.validate_email(email) isTrue

deftest_validate_email_invalid(self, validator):
"""测试非法的邮箱地址"""
    invalid_emails = [
'',                      # 空字符串
'invalid-email',         # 缺少@符号
'@example.com',          # 缺少用户名
'a' * 250 + '@test.com'# 超过长度限制
    ]
for email in invalid_emails:
assert validator.validate_email(email) isFalse

❌ 错误做法:测试代码和被测代码混在一起

# 错误示例:测试代码写在原文件里
classUserValidator:
defvalidate_email(self, email):
# ... 实现代码 ...
pass

# 测试代码不应该在这里!
deftest(self):
assert self.validate_email('test@test.com'isTrue

✅ 正确做法:测试代码单独放在test_*.py文件中

# user_validator.py - 只放业务代码
classUserValidator:
defvalidate_email(self, email):
# ... 实现代码 ...
pass

# test_user_validator.py - 测试代码单独存放
classTestUserValidator:
deftest_validate_email(self):
        validator = UserValidator()
assert validator.validate_email('test@test.com'isTrue

❌ 错误做法:盲目相信AI生成的测试

# AI生成的测试可能有问题
deftest_validate_age(self, validator):
# AI可能生成这样的测试,但逻辑不完整
assert validator.validate_age(25)  # 只检查返回值是否为真值

✅ 正确做法:人工审查AI生成的测试

# 人工优化后的测试
deftest_validate_age_valid(self, validator):
"""测试合法的年龄"""
    is_valid, error = validator.validate_age(25)
assert is_valid isTrue# 明确检查布尔值
assert error == ""# 明确检查错误信息

deftest_validate_age_invalid(self, validator):
"""测试非法的年龄"""
    is_valid, error = validator.validate_age(-1)
assert is_valid isFalse
assert"负数"in error   # 检查错误信息内容

❌ 错误做法:追求100%覆盖率而测试无意义的代码

# 不要为了覆盖率而测试getter/setter
classUser:
def__init__(self, name):
        self._name = name

    @property
defname(self):
return self._name

    @name.setter
defname(self, value):
        self._name = value

# 不需要测试这种简单的getter/setter
deftest_name_getter_setter():
    user = User("John")
assert user.name == "John"# 这种测试价值很低
    user.name = "Jane"
assert user.name == "Jane"

✅ 正确做法:优先测试业务逻辑

# 重点测试有业务逻辑的方法
classUser:
def__init__(self, name, age):
        self._name = name
        self._age = age

defis_adult(self):
"""判断是否成年 - 有业务逻辑,需要测试"""
return self._age >= 18

defget_discount(self):
"""计算折扣 - 有业务逻辑,需要测试"""
if self._age < 18:
return0.5# 未成年5折
elif self._age >= 60:
return0.7# 老人7折
return1.0# 成年人原价

# 测试业务逻辑
deftest_get_discount():
assert User("Child"10).get_discount() == 0.5
assert User("Adult"30).get_discount() == 1.0
assert User("Senior"65).get_discount() == 0.7

本章小结 & 下集预告

本章小结

今天我们学习了:

  1. 单元测试基础

    • 单元测试是对最小代码单元的验证
    • 代码覆盖率衡量测试的完整性,80%是合理目标
  2. AI生成单元测试

    • 使用Prompt模板让AI生成测试代码
    • 常用工具:Cursor、Claude Code、GitHub Copilot
    • AI生成的测试需要人工审查和优化
  3. 覆盖率检查

    • 使用pytest-cov插件生成覆盖率报告
    • HTML报告可以直观查看哪些代码没被覆盖
    • 追求覆盖率的同时要注重测试质量

下集预告

Day 44:待定标题(模块五:AI 调试与错误分析)

我们将进入新的模块,学习如何用AI工具进行代码调试和错误分析,包括:

  • 用AI解读复杂的错误堆栈
  • AI辅助的断点调试技巧
  • 自动生成错误修复建议

💡 课后作业

  1. 找一个你最近写的Python函数,用AI工具生成单元测试
  2. 运行 pytest --cov 检查覆盖率
  3. 尝试将覆盖率提升到80%以上
  4. 思考:AI生成的测试有哪些不足?如何改进?

📚 扩展阅读

  • pytest官方文档
  • coverage.py文档