为设定模块提供示例并使用len函数

问题描述

以下代码导致我的测试功能在运行时失败:

from hypothesis import given,example
import hypothesis.strategies as st
import unittest

class SomeObject():
    def __init__(self,symbol,value):
        self.__symbol = symbol
        self.__value = value

@st.composite
def sheet_names(draw,cnt=1,cnt_min_value=0):
    if (not cnt):
        cnt = draw(st.integers(min_value=cnt_min_value,max_value=3))
    return (cnt,draw(st.lists(st.text(min_size=1).filter(lambda x: '\n' not in x),min_size=cnt,max_size=cnt,unique=True)))

@st.composite
def get_objects(draw,min_cnt=0):
    cnt = draw(st.integers(min_value=min_cnt,max_value=3))
    symbols = draw(st.lists(st.text(min_size=1),unique=True))
    values = draw(st.lists(st.one_of(st.integers(),st.floats(allow_nan=False),st.text()),max_size=cnt))
    objects = list()
    for i in range(len(symbols)):
        objects.append(SomeObject(symbols[i],values[i]))
    return objects

class TestClass(unittest.TestCase):
    @given(sheet_names=sheet_names(cnt=False,cnt_min_value=1),specs=get_objects(min_cnt=1))
    @example(sheet_names=sheet_names(cnt=2),specs=get_objects(min_cnt=1))
    def test_example(self,sheet_names,specs):
        for i in range(len(sheet_names)):
            pass

错误消息是:

TypeError:“ LazyStrategy”类型的对象没有len()

,出现在函数test_example中(在for循环中)。如果我删除@ example-line,则代码可以正常运行,但不能确定@example中提到的情况是否已解决

问题:如何一方面编写通用测试(为此我需要len函数)并同时为假设命名明确的示例?

解决方法

正如Azat Ibrakov所说,您的问题是@example装饰器采用,而不是策略。例如:

# Bad - strategies don't work here!
@example(sheet_names=sheet_names(cnt=2),specs=get_objects(min_cnt=1))

# Good - passing values which could be generated.
@example(
    sheet_names=(2,["sheet1","sheet2]),specs=[<SomeObject ...>,<SomeObject ...>,<SomeObject ...>]
)

假设在version 5.36.1中添加了关于@example中的策略的明确警告。