Python进阶测试用例¶
测试目标: 验证Python高级特性和功能的正确性 测试类型: 单元测试、性能测试 涉及组件: 装饰器、生成器、上下文管理器、并发编程
📋 测试概述¶
测试目标¶
- 高级特性测试: 验证Python高级特性
- 并发测试: 验证并发和异步编程
- 性能测试: 评估代码执行效率
- 内存测试: 验证内存使用情况
测试环境¶
- Python版本: 3.8+
- 测试框架: pytest
- 性能分析: cProfile, timeit
🧪 测试用例列表¶
1. 装饰器测试¶
测试用例1.1: 基础装饰器¶
测试目标: 验证装饰器功能
测试代码:
Python
import pytest
from functools import wraps
import time
def test_basic_decorator():
"""测试基础装饰器"""
def my_decorator(func):
@wraps(func) # @wraps保留被装饰函数的元信息(名称、文档字符串等)
def wrapper(*args, **kwargs): # *args/**kwargs接收任意位置参数和关键字参数
print("Before function call")
result = func(*args, **kwargs)
print("After function call")
return result
return wrapper
@my_decorator
def greet(name):
return f"Hello, {name}!"
result = greet("Alice")
assert result == "Hello, Alice!"
# 验证函数名和文档字符串
assert greet.__name__ == "greet"
print("✓ 基础装饰器测试通过")
预期结果: 装饰器正确执行,函数名保持不变
测试用例1.2: 带参数的装饰器¶
测试目标: 验证带参数的装饰器
测试代码:
Python
def test_decorator_with_args():
"""测试带参数的装饰器"""
def repeat(times):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
results = []
for _ in range(times):
result = func(*args, **kwargs)
results.append(result)
return results
return wrapper
return decorator
@repeat(3)
def greet(name):
return f"Hello, {name}!"
results = greet("Alice")
assert results == ["Hello, Alice!", "Hello, Alice!", "Hello, Alice!"]
print("✓ 带参数的装饰器测试通过")
预期结果: 函数执行指定次数
测试用例1.3: 类装饰器¶
测试目标: 验证类装饰器
测试代码:
Python
def test_class_decorator():
"""测试类装饰器"""
def singleton(cls):
instances = {}
@wraps(cls)
def get_instance(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return get_instance
@singleton
class MyClass:
def __init__(self, value):
self.value = value
# 创建两个实例
instance1 = MyClass(10)
instance2 = MyClass(20)
# 验证是同一个实例
assert instance1 is instance2
assert instance1.value == 10 # 第一个创建的值
print("✓ 类装饰器测试通过")
预期结果: 类装饰器正确实现单例模式
2. 生成器测试¶
测试用例2.1: 基础生成器¶
测试目标: 验证生成器功能
测试代码:
Python
def test_basic_generator():
"""测试基础生成器"""
def simple_generator():
yield 1 # yield将函数变为生成器,惰性逐个产出值
yield 2
yield 3
# 获取生成器
gen = simple_generator()
# 使用next获取值
assert next(gen) == 1
assert next(gen) == 2
assert next(gen) == 3
# 使用for循环
gen = simple_generator()
result = list(gen)
assert result == [1, 2, 3]
print("✓ 基础生成器测试通过")
预期结果: 生成器正确生成值
测试用例2.2: 生成器表达式¶
测试目标: 验证生成器表达式
测试代码:
Python
def test_generator_expression():
"""测试生成器表达式"""
# 生成器表达式
squares = (x**2 for x in range(5))
# 验证是生成器
assert hasattr(squares, '__iter__') # hasattr()检查对象是否拥有指定属性
assert hasattr(squares, '__next__')
# 转换为列表
result = list(squares)
assert result == [0, 1, 4, 9, 16]
# 带条件的生成器表达式
even_squares = (x**2 for x in range(10) if x % 2 == 0)
result = list(even_squares)
assert result == [0, 4, 16, 36, 64]
print("✓ 生成器表达式测试通过")
预期结果: 生成器表达式正确工作
测试用例2.3: yield from¶
测试目标: 验证yield from
测试代码:
Python
def test_yield_from():
"""测试yield from"""
def sub_generator1():
yield 1
yield 2
def sub_generator2():
yield 3
yield 4
def main_generator():
yield from sub_generator1() # yield from委托给子生成器,简化嵌套yield
yield from sub_generator2()
yield 5
result = list(main_generator())
assert result == [1, 2, 3, 4, 5]
print("✓ yield from测试通过")
预期结果: yield from正确委托给子生成器
3. 上下文管理器测试¶
测试用例3.1: 基础上下文管理器¶
测试目标: 验证上下文管理器
测试代码:
Python
def test_context_manager():
"""测试上下文管理器"""
class MyContext:
def __enter__(self):
print("Entering context")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("Exiting context")
return False
# 使用with语句
with MyContext() as ctx:
assert ctx is not None
print("Inside context")
print("✓ 基础上下文管理器测试通过")
预期结果: 上下文管理器正确进入和退出
测试用例3.2: contextlib装饰器¶
测试目标: 验证contextlib装饰器
测试代码:
Python
from contextlib import contextmanager
def test_contextlib_decorator():
"""测试contextlib装饰器"""
@contextmanager # @contextmanager用yield将普通函数变为上下文管理器
def my_context():
print("Entering context")
try:
yield "resource"
finally:
print("Cleaning up")
# 使用with语句
with my_context() as resource:
assert resource == "resource"
print("Using resource")
print("✓ contextlib装饰器测试通过")
预期结果: contextlib装饰器正确工作
4. 并发编程测试¶
测试用例4.1: 多线程¶
测试目标: 验证多线程编程
测试代码:
Python
import threading
def test_multithreading():
"""测试多线程"""
results = []
def worker(value):
results.append(value * 2)
# 创建线程
threads = []
for i in range(5):
t = threading.Thread(target=worker, args=(i,)) # threading.Thread创建新线程执行并发任务
threads.append(t)
t.start()
# 等待所有线程完成
for t in threads:
t.join()
# 验证结果
assert len(results) == 5
assert set(results) == {0, 2, 4, 6, 8}
print("✓ 多线程测试通过")
预期结果: 多线程正确执行
测试用例4.2: 线程锁¶
测试目标: 验证线程锁
测试代码:
Python
def test_thread_lock():
"""测试线程锁"""
counter = 0
lock = threading.Lock()
def increment():
nonlocal counter # nonlocal声明引用外层函数的变量(非全局)
for _ in range(1000):
with lock:
counter += 1
# 创建线程
threads = []
for _ in range(10):
t = threading.Thread(target=increment)
threads.append(t)
t.start()
# 等待所有线程完成
for t in threads:
t.join()
# 验证结果
assert counter == 10000
print("✓ 线程锁测试通过")
预期结果: 线程锁正确保护共享资源
测试用例4.3: 异步编程¶
测试目标: 验证异步编程
测试代码:
Python
import asyncio
async def test_async_await():
"""测试async/await"""
async def fetch_data(delay): # async def定义协程函数,await暂停等待异步结果
await asyncio.sleep(delay)
return f"Data after {delay}s"
# 创建协程
coro1 = fetch_data(0.1)
coro2 = fetch_data(0.2)
# 并发执行
results = await asyncio.gather(coro1, coro2)
# 验证结果
assert len(results) == 2
assert "Data after 0.1s" in results[0]
assert "Data after 0.2s" in results[1]
print("✓ async/await测试通过")
def test_async_with_pytest():
"""在pytest中测试async函数"""
asyncio.run(test_async_await()) # asyncio.run()启动异步事件循环并执行协程
预期结果: 异步函数正确执行
5. 性能测试¶
测试用例5.1: 列表推导vs循环¶
测试目标: 对比列表推导和循环的性能
测试代码:
Python
import timeit
def test_list_comprehension_performance():
"""测试列表推导性能"""
# 列表推导
list_comp_time = timeit.timeit(
"[x**2 for x in range(1000)]",
number=1000,
globals=globals(),
)
# for循环
for_loop_time = timeit.timeit(
"""
result = []
for x in range(1000):
result.append(x**2)
""",
number=1000,
globals=globals(),
)
print(f"列表推导时间: {list_comp_time:.4f}s")
print(f"for循环时间: {for_loop_time:.4f}s")
# 列表推导应该更快
assert list_comp_time < for_loop_time
print("✓ 列表推导性能测试通过")
预期结果: 列表推导比for循环更快
测试用例5.2: 生成器vs列表¶
测试目标: 对比生成器和列表的内存使用
测试代码:
Python
import sys
def test_generator_memory():
"""测试生成器内存使用"""
# 列表
list_obj = [x**2 for x in range(1000000)]
list_size = sys.getsizeof(list_obj)
# 生成器
gen_obj = (x**2 for x in range(1000000))
gen_size = sys.getsizeof(gen_obj)
print(f"列表大小: {list_size / 1024:.2f} KB")
print(f"生成器大小: {gen_size / 1024:.2f} KB")
# 生成器应该占用更少内存
assert gen_size < list_size
print("✓ 生成器内存测试通过")
预期结果: 生成器占用更少内存
6. 元编程测试¶
测试用例6.1: 元类¶
测试目标: 验证元类
测试代码:
Python
def test_metaclass():
"""测试元类"""
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs): # __call__使实例可像函数一样被调用
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs) # super()调用父类方法
return cls._instances[cls]
class MyClass(metaclass=SingletonMeta):
def __init__(self, value):
self.value = value
# 创建两个实例
instance1 = MyClass(10)
instance2 = MyClass(20)
# 验证是同一个实例
assert instance1 is instance2
assert instance1.value == 10
print("✓ 元类测试通过")
预期结果: 元类正确实现单例模式
测试用例6.2: getattr__和__setattr¶
测试目标: 验证动态属性访问
测试代码:
Python
def test_dynamic_attributes():
"""测试动态属性访问"""
class DynamicAttributes:
def __init__(self):
self._data = {}
def __getattr__(self, name):
if name.startswith('_'):
raise AttributeError(name)
return self._data.get(name, f"Default: {name}")
def __setattr__(self, name, value):
if name.startswith('_'):
super().__setattr__(name, value)
else:
self._data[name] = value
obj = DynamicAttributes()
# 设置属性
obj.name = "Alice"
obj.age = 25
# 获取属性
assert obj.name == "Alice"
assert obj.age == 25
assert obj.city == "Default: city"
# 访问不存在的私有属性(_data 存在于 __dict__ 中,不会触发 __getattr__)
# __getattr__ 仅在常规属性查找失败时才被调用
assert isinstance(obj._data, dict) # _data 通过 super().__setattr__ 设置,可正常访问
# 访问不存在的私有属性会触发 __getattr__,从而抛出 AttributeError
try:
_ = obj._nonexistent
assert False, "Should raise AttributeError"
except AttributeError:
pass
print("✓ 动态属性访问测试通过")
预期结果: 动态属性访问正确工作
📊 测试执行¶
运行所有测试¶
Bash
# 运行所有测试
pytest tests/test_python_advanced.py -v
# 运行特定测试
pytest tests/test_python_advanced.py::test_basic_decorator -v
# 生成覆盖率报告
pytest tests/test_python_advanced.py --cov=python_advanced --cov-report=html
✅ 验证方法¶
1. 自动化验证¶
- 运行所有测试用例
- 检查断言是否通过
- 记录测试结果
2. 性能基准¶
- 建立性能基准
- 监控性能变化
- 优化性能瓶颈
3. 内存分析¶
- 使用memory_profiler分析内存
- 检查内存泄漏
- 优化内存使用
📝 测试报告¶
测试报告应包含:
- 测试概览
- 测试用例数量
- 通过/失败统计
-
代码覆盖率
-
详细结果
- 每个测试用例的结果
- 性能指标
-
内存使用情况
-
问题分析
- 失败原因分析
- 改进建议
- 后续计划
测试完成标准: 所有测试用例通过 推荐测试频率: 每次代码更新 测试维护周期: 每周