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

如何为自定义dataclasses定义Hypothesis策略?能否自动生成?

用Hypothesis自动生成Dataclass测试策略

当然有办法不用手动写每个dataclass的策略,Hypothesis自带的工具就能实现类似Rust arbitrary库的自动类型推导能力,甚至能适配自定义的限定类型(比如你用到的uint64、uint256),下面是具体实现方式:

1. 基础自动生成:直接用from_type

如果你的dataclass字段都是Hypothesis能自动识别的类型(比如int、bytes这类基础类型),直接调用st.from_type()就能生成对应策略:

from dataclasses import dataclass
import hypothesis.strategies as st

@dataclass
class Account:
    nonce: int
    balance: int
    code: bytes

# 一行生成Account的测试策略
account_strategy = st.from_type(Account)

2. 适配自定义限定类型:注册类型策略

针对你需要的uint64、uint256这类有范围约束的整数,你可以先定义好对应的策略,再注册给自定义类型,这样Hypothesis就能自动识别并使用对应策略:

from typing import NewType
import hypothesis.strategies as st

# 定义限定范围的整数策略
uint64 = st.integers(min_value=0, max_value=2**64 - 1)
uint256 = st.integers(min_value=0, max_value=2**256 - 1)

# 用NewType创建自定义类型别名
Uint64 = NewType('Uint64', int)
Uint256 = NewType('Uint256', int)

# 注册类型与策略的映射
st.register_type_strategy(Uint64, uint64)
st.register_type_strategy(Uint256, uint256)

# 定义dataclass时使用自定义类型
@dataclass
class Account:
    nonce: Uint64
    balance: Uint256
    code: bytes

# 自动生成符合要求的Account策略
account_strategy = st.from_type(Account)

3. 更灵活的控制:用Hypothesis的dataclass装饰器

如果需要给某些字段加特殊约束(比如code的字节长度限制),可以用hypothesis.extra.dataclasses里的dataclass装饰器代替标准库的,它会自动集成策略生成能力,还能直接给字段指定策略:

from hypothesis.extra.dataclasses import dataclass
from typing import NewType
import hypothesis.strategies as st

# 先注册自定义类型策略(同上)
Uint64 = NewType('Uint64', int)
Uint256 = NewType('Uint256', int)
st.register_type_strategy(Uint64, st.integers(min_value=0, max_value=2**64 -1))
st.register_type_strategy(Uint256, st.integers(min_value=0, max_value=2**256 -1))

@dataclass
class Account:
    nonce: Uint64
    balance: Uint256
    # 直接给code字段指定带长度限制的策略
    code: bytes = st.binary(min_size=0, max_size=1024).example()

# 自动生成策略
account_strategy = st.from_type(Account)

关于从原始字节缓冲区生成

如果一定要像Rust arbitrary那样从原始字节生成结构化数据,你可以先生成随机字节,再自己写解析逻辑映射到dataclass,但这种方式需要手动处理字节解析,容易出错,除非有特殊需求否则不推荐:

def bytes_to_account(raw_bytes: bytes) -> Account:
    # 按固定格式解析字节:前8字节是uint64的nonce,接下来32字节是uint256的balance,剩余是code
    nonce = Uint64(int.from_bytes(raw_bytes[:8], byteorder='big'))
    balance = Uint256(int.from_bytes(raw_bytes[8:40], byteorder='big'))
    code = raw_bytes[40:]
    return Account(nonce=nonce, balance=balance, code=code)

# 生成原始字节并映射为Account实例
account_from_bytes = st.binary(min_size=40).map(bytes_to_account)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 09:41:21