用 dataclass 减少测试数据样板代码
写业务测试时,经常会反复构造用户、订单或配置对象。字典写起来快,但没有字段提示,拼错键名也只有运行到测试时才暴露。Python 的 dataclass 可以用很少的代码给测试数据加上明确字段、默认值和可读的打印结果。
假设订单测试需要一组用户信息:
from dataclasses import dataclass
@dataclass
class User:
name: str
email: str
active: bool = True
现在创建测试数据时,字段名称和类型都直接写在类定义里:
user = User(
name="张明",
email="zhangming@example.com",
)
assert user.active is True
和字典相比,user.email 比 user["emial"] 更容易检查,编辑器和类型检查工具也能发现不存在的属性。调试时直接打印对象,会得到包含类名和全部字段的结果,日志比一串没有结构的大括号更清楚。
用默认值减少重复
大部分测试只关心一两个字段,其余内容可以使用固定默认值:
@dataclass
class CreateOrder:
user_id: int
product_id: int
quantity: int = 1
coupon: str | None = None
正常下单测试只传核心字段:
def test_create_order():
payload = CreateOrder(user_id=7, product_id=42)
assert payload.quantity == 1
assert payload.coupon is None
需要测试优惠券时,再显式覆盖对应字段。默认数据集中在一个地方,测试正文只保留与当前场景有关的信息。
可变默认值要使用 field
列表、字典和集合不能直接写成普通默认值,否则多个实例可能共享同一个对象。dataclasses.field 提供了工厂函数:
from dataclasses import dataclass, field
@dataclass
class Checkout:
user_id: int
items: list[str] = field(default_factory=list)
两个 Checkout 实例会得到各自的空列表:
first = Checkout(user_id=1)
second = Checkout(user_id=2)
first.items.append("键盘")
assert second.items == []
如果直接写 items: list[str] = [],Python 会抛出 ValueError,原因正是为了避免多个实例共用可变默认值。使用 default_factory 能把这个风险消除在定义阶段。
不要急着模拟业务实体
dataclass 适合表达测试入参和轻量数据结构,但不应为了测试再造一套业务模型。接口的请求体本来就用字典时,可以让 dataclass 只负责生成数据,最后再转换成字典:
from dataclasses import asdict
payload = asdict(CreateOrder(user_id=7, product_id=42))
这样既保留构造数据时的字段检查,也不会影响被测代码接收的原始格式。请求参数需要特殊序列化时,再增加一个明确的转换函数。
测试数据的目标是让场景一眼可见。字段少时直接传参最清楚;字段多、重复多或容易拼错时,再引入 dataclass。把默认值、可变对象和序列化边界处理好,测试会更易读,也更容易长期维护。
- 点赞
- 收藏
- 关注作者
评论(0)