You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用pytest与Hypothesis自动生成Address数据类实例失败求助

如何让Hypothesis自动生成attrs数据类的测试策略?

问题背景

你已通过手动定义st.builds()策略成功让Hypothesis捕获到Address类的测试bug,但尝试st.register_type_strategy(Address)或直接@given(Address)时,无法实现自动生成策略的效果。

问题根源

  1. st.register_type_strategy用法错误:该函数要求传入「目标类 + 对应的策略实例」,而非仅传入类本身
  2. 直接传入类不生效:Hypothesis不会自动将类对象解析为测试策略,需明确触发类型推导逻辑

正确解决方案

方案1:使用st.from_type()自动推导(推荐)

这是最简洁的方式,Hypothesis会根据类的类型注解自动生成匹配的策略,完美支持attrs数据类:

import attrs
from hypothesis import given
import hypothesis.strategies as st

@attrs.frozen(kw_only=True)
class Address:
    street: str
    city: str

# 用st.from_type()自动推导Address的测试策略
@given(st.from_type(Address))
def test_proper_address(address):
    assert len(address.city) < 4

运行pytest后,会和手动定义策略一样捕获到city='0000'的反例。

方案2:正确注册全局类型策略

如果需要在多个测试中复用Address的策略,可以通过st.register_type_strategy()完成全局注册,注意必须传入策略实例:

import attrs
from hypothesis import given
import hypothesis.strategies as st

@attrs.frozen(kw_only=True)
class Address:
    street: str
    city: str

# 注册Address类对应的策略
st.register_type_strategy(Address, st.builds(Address, street=st.text(), city=st.text()))

# 后续测试可直接传入Address类
@given(Address)
def test_proper_address(address):
    assert len(address.city) < 4

方案3:依赖自动识别(需环境达标)

确保你的环境满足以下条件时,Hypothesis可自动识别attrs类的策略:

  • 安装最新版本的Hypothesis(内置attrs支持,无需额外依赖)
  • 类的所有字段都有完整的类型注解
    此时可通过隐式推导,但最可靠的仍是st.from_type()。

验证效果

无论使用哪种方案,运行pytest后都会得到相同的错误输出,成功捕获测试bug:

address = Address(street='', city='0000')

    @given(st.from_type(Address))
    def test_proper_address(address):
>       assert len(address.city) < 4
E       AssertionError: assert 4 < 4
E        +  where 4 = len('0000')
E        +    where '0000' = Address(street='', city='0000').city

main.py:23: AssertionError

内容的提问来源于stack exchange,提问作者OrenIshShalom

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 21:25:23